mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
14 Commits
pr_4387
...
tidy-up-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6e8fbb54a | ||
|
|
28e9ccd372 | ||
|
|
9a66d9addd | ||
|
|
8843bda477 | ||
|
|
3278303eec | ||
|
|
f5fd6e3a36 | ||
|
|
b20c5f3a8d | ||
|
|
068b93befa | ||
|
|
bffd1d61b2 | ||
|
|
4788b81220 | ||
|
|
9a07fc03c6 | ||
|
|
954f518030 | ||
|
|
9f8ff71757 | ||
|
|
06dd59dc81 |
@@ -77,6 +77,53 @@ function CommsConnection(ws, user) {
|
|||||||
log.trace("comms.close "+self.session);
|
log.trace("comms.close "+self.session);
|
||||||
removeActiveConnection(self);
|
removeActiveConnection(self);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleAuthPacket = function(msg) {
|
||||||
|
Tokens.get(msg.auth).then(function(client) {
|
||||||
|
if (client) {
|
||||||
|
Users.get(client.user).then(function(user) {
|
||||||
|
if (user) {
|
||||||
|
self.user = user;
|
||||||
|
log.audit({event: "comms.auth",user:self.user});
|
||||||
|
completeConnection(msg, client.scope,msg.auth,true);
|
||||||
|
} else {
|
||||||
|
log.audit({event: "comms.auth.fail"});
|
||||||
|
completeConnection(msg, null,null,false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Users.tokens(msg.auth).then(function(user) {
|
||||||
|
if (user) {
|
||||||
|
self.user = user;
|
||||||
|
log.audit({event: "comms.auth",user:self.user});
|
||||||
|
completeConnection(msg, user.permissions,msg.auth,true);
|
||||||
|
} else {
|
||||||
|
log.audit({event: "comms.auth.fail"});
|
||||||
|
completeConnection(msg, null,null,false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const completeConnection = function(msg, userScope, session, sendAck) {
|
||||||
|
try {
|
||||||
|
if (!userScope || !Permissions.hasPermission(userScope,"status.read")) {
|
||||||
|
ws.send(JSON.stringify({auth:"fail"}));
|
||||||
|
ws.close();
|
||||||
|
} else {
|
||||||
|
pendingAuth = false;
|
||||||
|
addActiveConnection(self);
|
||||||
|
self.token = msg.auth;
|
||||||
|
if (sendAck) {
|
||||||
|
ws.send(JSON.stringify({auth:"ok"}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
// Just in case the socket closes before we attempt
|
||||||
|
// to send anything.
|
||||||
|
}
|
||||||
|
}
|
||||||
ws.on('message', function(data,flags) {
|
ws.on('message', function(data,flags) {
|
||||||
var msg = null;
|
var msg = null;
|
||||||
try {
|
try {
|
||||||
@@ -86,68 +133,34 @@ function CommsConnection(ws, user) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pendingAuth) {
|
if (!pendingAuth) {
|
||||||
if (msg.subscribe) {
|
if (msg.auth) {
|
||||||
|
handleAuthPacket(msg)
|
||||||
|
} else if (msg.subscribe) {
|
||||||
self.subscribe(msg.subscribe);
|
self.subscribe(msg.subscribe);
|
||||||
// handleRemoteSubscription(ws,msg.subscribe);
|
// handleRemoteSubscription(ws,msg.subscribe);
|
||||||
|
} else if (msg.topic) {
|
||||||
|
runtimeAPI.comms.receive({
|
||||||
|
user: self.user,
|
||||||
|
client: self,
|
||||||
|
topic: msg.topic,
|
||||||
|
data: msg.data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var completeConnection = function(userScope,session,sendAck) {
|
|
||||||
try {
|
|
||||||
if (!userScope || !Permissions.hasPermission(userScope,"status.read")) {
|
|
||||||
ws.send(JSON.stringify({auth:"fail"}));
|
|
||||||
ws.close();
|
|
||||||
} else {
|
|
||||||
pendingAuth = false;
|
|
||||||
addActiveConnection(self);
|
|
||||||
self.token = msg.auth;
|
|
||||||
if (sendAck) {
|
|
||||||
ws.send(JSON.stringify({auth:"ok"}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
console.log(err.stack);
|
|
||||||
// Just in case the socket closes before we attempt
|
|
||||||
// to send anything.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (msg.auth) {
|
if (msg.auth) {
|
||||||
Tokens.get(msg.auth).then(function(client) {
|
handleAuthPacket(msg)
|
||||||
if (client) {
|
|
||||||
Users.get(client.user).then(function(user) {
|
|
||||||
if (user) {
|
|
||||||
self.user = user;
|
|
||||||
log.audit({event: "comms.auth",user:self.user});
|
|
||||||
completeConnection(client.scope,msg.auth,true);
|
|
||||||
} else {
|
|
||||||
log.audit({event: "comms.auth.fail"});
|
|
||||||
completeConnection(null,null,false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Users.tokens(msg.auth).then(function(user) {
|
|
||||||
if (user) {
|
|
||||||
self.user = user;
|
|
||||||
log.audit({event: "comms.auth",user:self.user});
|
|
||||||
completeConnection(user.permissions,msg.auth,true);
|
|
||||||
} else {
|
|
||||||
log.audit({event: "comms.auth.fail"});
|
|
||||||
completeConnection(null,null,false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
if (anonymousUser) {
|
if (anonymousUser) {
|
||||||
log.audit({event: "comms.auth",user:anonymousUser});
|
log.audit({event: "comms.auth",user:anonymousUser});
|
||||||
self.user = anonymousUser;
|
self.user = anonymousUser;
|
||||||
completeConnection(anonymousUser.permissions,null,false);
|
completeConnection(msg, anonymousUser.permissions, null, false);
|
||||||
//TODO: duplicated code - pull non-auth message handling out
|
//TODO: duplicated code - pull non-auth message handling out
|
||||||
if (msg.subscribe) {
|
if (msg.subscribe) {
|
||||||
self.subscribe(msg.subscribe);
|
self.subscribe(msg.subscribe);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.audit({event: "comms.auth.fail"});
|
log.audit({event: "comms.auth.fail"});
|
||||||
completeConnection(null,null,false);
|
completeConnection(msg, null,null,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -924,7 +924,14 @@
|
|||||||
"date": "horodatage",
|
"date": "horodatage",
|
||||||
"jsonata": "expression",
|
"jsonata": "expression",
|
||||||
"env": "variable d'environnement",
|
"env": "variable d'environnement",
|
||||||
"cred": "identifiant"
|
"cred": "identifiant",
|
||||||
|
"conf-types": "noeud de configuration"
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"format": {
|
||||||
|
"timestamp": "millisecondes depuis l'époque",
|
||||||
|
"object": "Objet de date JavaScript"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editableList": {
|
"editableList": {
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ RED.comms = (function() {
|
|||||||
var reconnectAttempts = 0;
|
var reconnectAttempts = 0;
|
||||||
var active = false;
|
var active = false;
|
||||||
|
|
||||||
|
RED.events.on('login', function(username) {
|
||||||
|
// User has logged in
|
||||||
|
// Need to upgrade the connection to be authenticated
|
||||||
|
if (ws && ws.readyState == 1) {
|
||||||
|
const auth_tokens = RED.settings.get("auth-tokens");
|
||||||
|
ws.send(JSON.stringify({auth:auth_tokens.access_token}))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function connectWS() {
|
function connectWS() {
|
||||||
active = true;
|
active = true;
|
||||||
var wspath;
|
var wspath;
|
||||||
@@ -56,6 +65,7 @@ RED.comms = (function() {
|
|||||||
ws.send(JSON.stringify({subscribe:t}));
|
ws.send(JSON.stringify({subscribe:t}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
emit('connect')
|
||||||
}
|
}
|
||||||
|
|
||||||
ws = new WebSocket(wspath);
|
ws = new WebSocket(wspath);
|
||||||
@@ -180,9 +190,53 @@ RED.comms = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function send(topic, msg) {
|
||||||
|
if (ws && ws.readyState == 1) {
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
topic,
|
||||||
|
data: msg
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventHandlers = {};
|
||||||
|
function on(evt,func) {
|
||||||
|
eventHandlers[evt] = eventHandlers[evt]||[];
|
||||||
|
eventHandlers[evt].push(func);
|
||||||
|
}
|
||||||
|
function off(evt,func) {
|
||||||
|
const handler = eventHandlers[evt];
|
||||||
|
if (handler) {
|
||||||
|
for (let i=0;i<handler.length;i++) {
|
||||||
|
if (handler[i] === func) {
|
||||||
|
handler.splice(i,1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function emit() {
|
||||||
|
const evt = arguments[0]
|
||||||
|
const args = Array.prototype.slice.call(arguments,1);
|
||||||
|
if (eventHandlers[evt]) {
|
||||||
|
let cpyHandlers = [...eventHandlers[evt]];
|
||||||
|
for (let i=0;i<cpyHandlers.length;i++) {
|
||||||
|
try {
|
||||||
|
cpyHandlers[i].apply(null, args);
|
||||||
|
} catch(err) {
|
||||||
|
console.warn("RED.comms.emit error: ["+evt+"] "+(err.toString()));
|
||||||
|
console.warn(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connect: connectWS,
|
connect: connectWS,
|
||||||
subscribe: subscribe,
|
subscribe: subscribe,
|
||||||
unsubscribe:unsubscribe
|
unsubscribe:unsubscribe,
|
||||||
|
on,
|
||||||
|
off,
|
||||||
|
send
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -153,10 +153,6 @@ RED.envVar = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init(done) {
|
function init(done) {
|
||||||
if (!RED.user.hasPermission("settings.write")) {
|
|
||||||
RED.notify(RED._("user.errors.settings"),"error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RED.userSettings.add({
|
RED.userSettings.add({
|
||||||
id:'envvar',
|
id:'envvar',
|
||||||
title: RED._("env-var.environment"),
|
title: RED._("env-var.environment"),
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ RED.palette = (function() {
|
|||||||
var categoryContainers = {};
|
var categoryContainers = {};
|
||||||
var sidebarControls;
|
var sidebarControls;
|
||||||
|
|
||||||
|
let paletteState = { filter: "", collapsed: [] };
|
||||||
|
|
||||||
|
let filterRefreshTimeout
|
||||||
|
|
||||||
function createCategory(originalCategory,rootCategory,category,ns) {
|
function createCategory(originalCategory,rootCategory,category,ns) {
|
||||||
if ($("#red-ui-palette-base-category-"+rootCategory).length === 0) {
|
if ($("#red-ui-palette-base-category-"+rootCategory).length === 0) {
|
||||||
createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory);
|
createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory);
|
||||||
@@ -60,20 +64,57 @@ RED.palette = (function() {
|
|||||||
catDiv.data('label',label);
|
catDiv.data('label',label);
|
||||||
categoryContainers[category] = {
|
categoryContainers[category] = {
|
||||||
container: catDiv,
|
container: catDiv,
|
||||||
close: function() {
|
hide: function (instant) {
|
||||||
|
if (instant) {
|
||||||
|
catDiv.hide()
|
||||||
|
} else {
|
||||||
|
catDiv.slideUp()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
catDiv.show()
|
||||||
|
},
|
||||||
|
isOpen: function () {
|
||||||
|
return !!catDiv.hasClass("red-ui-palette-open")
|
||||||
|
},
|
||||||
|
getNodeCount: function (visibleOnly) {
|
||||||
|
const nodes = catDiv.find(".red-ui-palette-node")
|
||||||
|
if (visibleOnly) {
|
||||||
|
return nodes.filter(function() { return $(this).css('display') !== 'none'}).length
|
||||||
|
} else {
|
||||||
|
return nodes.length
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function(instant, skipSaveState) {
|
||||||
catDiv.removeClass("red-ui-palette-open");
|
catDiv.removeClass("red-ui-palette-open");
|
||||||
catDiv.addClass("red-ui-palette-closed");
|
catDiv.addClass("red-ui-palette-closed");
|
||||||
$("#red-ui-palette-base-category-"+category).slideUp();
|
if (instant) {
|
||||||
|
$("#red-ui-palette-base-category-"+category).hide();
|
||||||
|
} else {
|
||||||
|
$("#red-ui-palette-base-category-"+category).slideUp();
|
||||||
|
}
|
||||||
$("#red-ui-palette-header-"+category+" i").removeClass("expanded");
|
$("#red-ui-palette-header-"+category+" i").removeClass("expanded");
|
||||||
|
if (!skipSaveState) {
|
||||||
|
if (!paletteState.collapsed.includes(category)) {
|
||||||
|
paletteState.collapsed.push(category);
|
||||||
|
savePaletteState();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
open: function() {
|
open: function(skipSaveState) {
|
||||||
catDiv.addClass("red-ui-palette-open");
|
catDiv.addClass("red-ui-palette-open");
|
||||||
catDiv.removeClass("red-ui-palette-closed");
|
catDiv.removeClass("red-ui-palette-closed");
|
||||||
$("#red-ui-palette-base-category-"+category).slideDown();
|
$("#red-ui-palette-base-category-"+category).slideDown();
|
||||||
$("#red-ui-palette-header-"+category+" i").addClass("expanded");
|
$("#red-ui-palette-header-"+category+" i").addClass("expanded");
|
||||||
|
if (!skipSaveState) {
|
||||||
|
if (paletteState.collapsed.includes(category)) {
|
||||||
|
paletteState.collapsed.splice(paletteState.collapsed.indexOf(category), 1);
|
||||||
|
savePaletteState();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
if (catDiv.hasClass("red-ui-palette-open")) {
|
if (categoryContainers[category].isOpen()) {
|
||||||
categoryContainers[category].close();
|
categoryContainers[category].close();
|
||||||
} else {
|
} else {
|
||||||
categoryContainers[category].open();
|
categoryContainers[category].open();
|
||||||
@@ -415,8 +456,16 @@ RED.palette = (function() {
|
|||||||
|
|
||||||
var categoryNode = $("#red-ui-palette-container-"+rootCategory);
|
var categoryNode = $("#red-ui-palette-container-"+rootCategory);
|
||||||
if (categoryNode.find(".red-ui-palette-node").length === 1) {
|
if (categoryNode.find(".red-ui-palette-node").length === 1) {
|
||||||
categoryContainers[rootCategory].open();
|
if (!paletteState?.collapsed?.includes(rootCategory)) {
|
||||||
|
categoryContainers[rootCategory].open();
|
||||||
|
} else {
|
||||||
|
categoryContainers[rootCategory].close(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
clearTimeout(filterRefreshTimeout)
|
||||||
|
filterRefreshTimeout = setTimeout(() => {
|
||||||
|
refreshFilter()
|
||||||
|
}, 200)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,7 +565,8 @@ RED.palette = (function() {
|
|||||||
paletteNode.css("backgroundColor", sf.color);
|
paletteNode.css("backgroundColor", sf.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterChange(val) {
|
function refreshFilter() {
|
||||||
|
const val = $("#red-ui-palette-search input").val()
|
||||||
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
|
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
|
||||||
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
|
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
|
||||||
var currentLabel = $(el).attr("data-palette-label");
|
var currentLabel = $(el).attr("data-palette-label");
|
||||||
@@ -528,16 +578,26 @@ RED.palette = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (var category in categoryContainers) {
|
for (let category in categoryContainers) {
|
||||||
if (categoryContainers.hasOwnProperty(category)) {
|
if (categoryContainers.hasOwnProperty(category)) {
|
||||||
if (categoryContainers[category].container
|
const categorySection = categoryContainers[category]
|
||||||
.find(".red-ui-palette-node")
|
if (categorySection.getNodeCount(true) === 0) {
|
||||||
.filter(function() { return $(this).css('display') !== 'none'}).length === 0) {
|
categorySection.hide()
|
||||||
categoryContainers[category].close();
|
|
||||||
categoryContainers[category].container.slideUp();
|
|
||||||
} else {
|
} else {
|
||||||
categoryContainers[category].open();
|
categorySection.show()
|
||||||
categoryContainers[category].container.show();
|
if (val) {
|
||||||
|
// There is a filter being applied and it has matched
|
||||||
|
// something in this category - show the contents
|
||||||
|
categorySection.open(true)
|
||||||
|
} else {
|
||||||
|
// No filter. Only show the category if it isn't in lastState
|
||||||
|
if (!paletteState.collapsed.includes(category)) {
|
||||||
|
categorySection.open(true)
|
||||||
|
} else if (categorySection.isOpen()) {
|
||||||
|
// This section should be collapsed but isn't - so make it so
|
||||||
|
categorySection.close(true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -553,6 +613,9 @@ RED.palette = (function() {
|
|||||||
|
|
||||||
$("#red-ui-palette > .red-ui-palette-spinner").show();
|
$("#red-ui-palette > .red-ui-palette-spinner").show();
|
||||||
|
|
||||||
|
RED.events.on('logout', function () {
|
||||||
|
RED.settings.removeLocal('palette-state')
|
||||||
|
})
|
||||||
|
|
||||||
RED.events.on('registry:node-type-added', function(nodeType) {
|
RED.events.on('registry:node-type-added', function(nodeType) {
|
||||||
var def = RED.nodes.getType(nodeType);
|
var def = RED.nodes.getType(nodeType);
|
||||||
@@ -596,14 +659,14 @@ RED.palette = (function() {
|
|||||||
|
|
||||||
RED.events.on("subflows:change",refreshSubflow);
|
RED.events.on("subflows:change",refreshSubflow);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$("#red-ui-palette-search input").searchBox({
|
$("#red-ui-palette-search input").searchBox({
|
||||||
delay: 100,
|
delay: 100,
|
||||||
change: function() {
|
change: function() {
|
||||||
filterChange($(this).val());
|
refreshFilter();
|
||||||
|
paletteState.filter = $(this).val();
|
||||||
|
savePaletteState();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
sidebarControls = $('<div class="red-ui-sidebar-control-left"><i class="fa fa-chevron-left"></i></div>').appendTo($("#red-ui-palette"));
|
sidebarControls = $('<div class="red-ui-sidebar-control-left"><i class="fa fa-chevron-left"></i></div>').appendTo($("#red-ui-palette"));
|
||||||
RED.popover.tooltip(sidebarControls,RED._("keyboard.togglePalette"),"core:toggle-palette");
|
RED.popover.tooltip(sidebarControls,RED._("keyboard.togglePalette"),"core:toggle-palette");
|
||||||
@@ -669,7 +732,23 @@ RED.palette = (function() {
|
|||||||
togglePalette(state);
|
togglePalette(state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
paletteState = JSON.parse(RED.settings.getLocal("palette-state") || '{"filter":"", "collapsed": []}');
|
||||||
|
if (paletteState.filter) {
|
||||||
|
// Apply the category filter
|
||||||
|
$("#red-ui-palette-search input").searchBox("value", paletteState.filter);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Unexpected error loading palette state from localStorage: ", error);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
// Lazily tidy up any categories that haven't been reloaded
|
||||||
|
paletteState.collapsed = paletteState.collapsed.filter(category => !!categoryContainers[category])
|
||||||
|
savePaletteState()
|
||||||
|
}, 10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePalette(state) {
|
function togglePalette(state) {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
$("#red-ui-main-container").addClass("red-ui-palette-closed");
|
$("#red-ui-main-container").addClass("red-ui-palette-closed");
|
||||||
@@ -689,6 +768,15 @@ RED.palette = (function() {
|
|||||||
})
|
})
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function savePaletteState() {
|
||||||
|
try {
|
||||||
|
RED.settings.setLocal("palette-state", JSON.stringify(paletteState));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Unexpected error saving palette state to localStorage: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
add:addNodeType,
|
add:addNodeType,
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ RED.user = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
|
RED.events.emit('logout')
|
||||||
var tokens = RED.settings.get("auth-tokens");
|
var tokens = RED.settings.get("auth-tokens");
|
||||||
var token = tokens?tokens.access_token:"";
|
var token = tokens?tokens.access_token:"";
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -225,6 +226,7 @@ RED.user = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
$('<i class="fa fa-user"></i>').appendTo("#red-ui-header-button-user");
|
||||||
} else {
|
} else {
|
||||||
RED.menu.addItem("red-ui-header-button-user",{
|
RED.menu.addItem("red-ui-header-button-user",{
|
||||||
id:"usermenu-item-username",
|
id:"usermenu-item-username",
|
||||||
@@ -237,6 +239,15 @@ RED.user = (function() {
|
|||||||
RED.user.logout();
|
RED.user.logout();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const userMenu = $("#red-ui-header-button-user")
|
||||||
|
userMenu.empty()
|
||||||
|
if (RED.settings.user.image) {
|
||||||
|
$('<span class="user-profile"></span>').css({
|
||||||
|
backgroundImage: "url("+RED.settings.user.image+")",
|
||||||
|
}).appendTo(userMenu);
|
||||||
|
} else {
|
||||||
|
$('<i class="fa fa-user"></i>').appendTo(userMenu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -247,14 +258,6 @@ RED.user = (function() {
|
|||||||
|
|
||||||
var userMenu = $('<li><a id="red-ui-header-button-user" class="button hide" href="#"></a></li>')
|
var userMenu = $('<li><a id="red-ui-header-button-user" class="button hide" href="#"></a></li>')
|
||||||
.prependTo(".red-ui-header-toolbar");
|
.prependTo(".red-ui-header-toolbar");
|
||||||
if (RED.settings.user.image) {
|
|
||||||
$('<span class="user-profile"></span>').css({
|
|
||||||
backgroundImage: "url("+RED.settings.user.image+")",
|
|
||||||
}).appendTo(userMenu.find("a"));
|
|
||||||
} else {
|
|
||||||
$('<i class="fa fa-user"></i>').appendTo(userMenu.find("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
RED.menu.init({id:"red-ui-header-button-user",
|
RED.menu.init({id:"red-ui-header-button-user",
|
||||||
options: []
|
options: []
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,25 +63,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.red-ui-header-toolbar {
|
.red-ui-header-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
|
align-items: stretch;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
height: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 40px;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 0px 12px;
|
padding: 0px 12px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -271,13 +275,13 @@
|
|||||||
color: var(--red-ui-header-menu-heading-color);
|
color: var(--red-ui-header-menu-heading-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#red-ui-header-button-user .user-profile {
|
.user-profile {
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 40px;
|
width: 30px;
|
||||||
height: 35px;
|
height: 30px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export default {
|
|||||||
{
|
{
|
||||||
title: {
|
title: {
|
||||||
"en-US": "Timestamp formatting options",
|
"en-US": "Timestamp formatting options",
|
||||||
"ja": "タイムスタンプの形式の項目"
|
"ja": "タイムスタンプの形式の項目",
|
||||||
|
"fr": "Options de formatage de l'horodatage"
|
||||||
},
|
},
|
||||||
image: 'images/nr4-timestamp-formatting.png',
|
image: 'images/nr4-timestamp-formatting.png',
|
||||||
description: {
|
description: {
|
||||||
@@ -34,13 +35,21 @@ export default {
|
|||||||
<li>エポックからのミリ秒 - 従来動作と同じになるタイムスタンプの項目</li>
|
<li>エポックからのミリ秒 - 従来動作と同じになるタイムスタンプの項目</li>
|
||||||
<li>ISO 8601 - 多くのシステムで使用されている共通の形式</li>
|
<li>ISO 8601 - 多くのシステムで使用されている共通の形式</li>
|
||||||
<li>JavaScript日付オブジェクト</li>
|
<li>JavaScript日付オブジェクト</li>
|
||||||
|
</ul>`,
|
||||||
|
"fr": `<p>Les noeuds qui vous permettent de définir un horodatage disposent désormais d'options sur le format dans lequel cet horodatage peut être défini.</p>
|
||||||
|
<p>Nous gardons les choses simples en proposant trois options :<p>
|
||||||
|
<ul>
|
||||||
|
<li>Millisecondes depuis l'époque : il s'agit du comportement existant de l'option d'horodatage</li>
|
||||||
|
<li>ISO 8601 : un format commun utilisé par de nombreux systèmes</li>
|
||||||
|
<li>Objet Date JavaScript</li>
|
||||||
</ul>`
|
</ul>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: {
|
title: {
|
||||||
"en-US": "Auto-complete of flow/global and env types",
|
"en-US": "Auto-complete of flow/global and env types",
|
||||||
"ja": "フロー/グローバル、環境変数の型の自動補完"
|
"ja": "フロー/グローバル、環境変数の型の自動補完",
|
||||||
|
"fr": "Saisie automatique des types de flux/global et env"
|
||||||
},
|
},
|
||||||
image: 'images/nr4-auto-complete.png',
|
image: 'images/nr4-auto-complete.png',
|
||||||
description: {
|
description: {
|
||||||
@@ -48,13 +57,17 @@ export default {
|
|||||||
now all include auto-complete suggestions based on the live state of your flows.</p>
|
now all include auto-complete suggestions based on the live state of your flows.</p>
|
||||||
`,
|
`,
|
||||||
"ja": `<p><code>flow</code>/<code>global</code>コンテキストや<code>env</code>の入力を、現在のフローの状態をもとに自動補完で提案するようになりました。</p>
|
"ja": `<p><code>flow</code>/<code>global</code>コンテキストや<code>env</code>の入力を、現在のフローの状態をもとに自動補完で提案するようになりました。</p>
|
||||||
`
|
`,
|
||||||
|
"fr": `<p>Les entrées contextuelles <code>flow</code>/<code>global</code> et l'entrée <code>env</code>
|
||||||
|
incluent désormais des suggestions de saisie semi-automatique basées sur l'état actuel de vos flux.</p>
|
||||||
|
`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: {
|
title: {
|
||||||
"en-US": "Config node customisation in Subflows",
|
"en-US": "Config node customisation in Subflows",
|
||||||
"ja": "サブフローでの設定ノードのカスタマイズ"
|
"ja": "サブフローでの設定ノードのカスタマイズ",
|
||||||
|
"fr": "Personnalisation du noeud de configuration dans les sous-flux"
|
||||||
},
|
},
|
||||||
image: 'images/nr4-sf-config.png',
|
image: 'images/nr4-sf-config.png',
|
||||||
description: {
|
description: {
|
||||||
@@ -65,6 +78,11 @@ export default {
|
|||||||
`,
|
`,
|
||||||
"ja": `<p>サブフローをカスタマイズして、選択した型の異なる設定ノードを各インスタンスが使用できるようになりました。</p>
|
"ja": `<p>サブフローをカスタマイズして、選択した型の異なる設定ノードを各インスタンスが使用できるようになりました。</p>
|
||||||
<p>例えば、MQTTブローカへ接続し、メッセージ受信と後処理を行うサブフローの各インスタンスに異なるブローカを指定することも可能です。</p>
|
<p>例えば、MQTTブローカへ接続し、メッセージ受信と後処理を行うサブフローの各インスタンスに異なるブローカを指定することも可能です。</p>
|
||||||
|
`,
|
||||||
|
"fr": `<p>Les sous-flux peuvent désormais être personnalisés pour permettre à chaque instance d'utiliser un
|
||||||
|
noeud de configuration d'un type sélectionné.</p>
|
||||||
|
<p>Par exemple, chaque instance d'un sous-flux qui se connecte à un courtier MQTT et effectue un post-traitement
|
||||||
|
des messages reçus peut être pointée vers un autre courtier.</p>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -90,6 +108,14 @@ export default {
|
|||||||
<li>WebSocketノードのカスタマイズ可能なヘッダ</li>
|
<li>WebSocketノードのカスタマイズ可能なヘッダ</li>
|
||||||
<li>Splitノードは、メッセージプロパティで操作できるようになりました</li>
|
<li>Splitノードは、メッセージプロパティで操作できるようになりました</li>
|
||||||
<li>他にも沢山あります...</li>
|
<li>他にも沢山あります...</li>
|
||||||
|
</ul>`,
|
||||||
|
"fr": `<p>Les noeuds principaux ont reçu de nombreux correctifs mineurs ainsi que des améliorations. La documentation a été mise à jour.
|
||||||
|
Consultez le journal des modifications dans la barre latérale d'aide pour une liste complète. Ci-dessous, les changements les plus importants :</p>
|
||||||
|
<ul>
|
||||||
|
<li>Un mode CSV entièrement conforme à la norme RFC4180</li>
|
||||||
|
<li>En-têtes personnalisables pour le noeud WebSocket</li>
|
||||||
|
<li>Le noeud Split peut désormais fonctionner sur n'importe quelle propriété de message</li>
|
||||||
|
<li>Et bien plus encore...</li>
|
||||||
</ul>`
|
</ul>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/node_modules/@node-red/nodes/locales/fr/common/91-global-config.html
vendored
Normal file
3
packages/node_modules/@node-red/nodes/locales/fr/common/91-global-config.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<script type="text/html" data-help-name="global-config">
|
||||||
|
<p>Un noeud pour contenir la configuration globale des flux.</p>
|
||||||
|
</script>
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
},
|
},
|
||||||
"catch": {
|
"catch": {
|
||||||
"catch": "catch : tout",
|
"catch": "catch : tout",
|
||||||
|
"catchGroup": "catch: groupe",
|
||||||
"catchNodes": "catch : __number__",
|
"catchNodes": "catch : __number__",
|
||||||
"catchUncaught": "catch : non capturé",
|
"catchUncaught": "catch : non capturé",
|
||||||
"label": {
|
"label": {
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"status": "statut : tout",
|
"status": "statut : tout",
|
||||||
|
"statusGroup": "statut: groupe",
|
||||||
"statusNodes": "statut : __number__",
|
"statusNodes": "statut : __number__",
|
||||||
"label": {
|
"label": {
|
||||||
"source": "Signaler l'état de",
|
"source": "Signaler l'état de",
|
||||||
@@ -250,7 +252,8 @@
|
|||||||
"initialize": "Au démarrage",
|
"initialize": "Au démarrage",
|
||||||
"finalize": "À l'arrêt",
|
"finalize": "À l'arrêt",
|
||||||
"outputs": "Sorties",
|
"outputs": "Sorties",
|
||||||
"modules": "Modules"
|
"modules": "Modules",
|
||||||
|
"timeout": "Délai d'attente"
|
||||||
},
|
},
|
||||||
"text": {
|
"text": {
|
||||||
"initialize": "// Le code ajouté ici sera exécuté une fois\n// à chaque démarrage du noeud.\n",
|
"initialize": "// Le code ajouté ici sera exécuté une fois\n// à chaque démarrage du noeud.\n",
|
||||||
@@ -847,7 +850,13 @@
|
|||||||
"newline": "Nouvelle ligne",
|
"newline": "Nouvelle ligne",
|
||||||
"usestrings": "Analyser les valeurs numériques",
|
"usestrings": "Analyser les valeurs numériques",
|
||||||
"include_empty_strings": "Inclure les chaînes vides",
|
"include_empty_strings": "Inclure les chaînes vides",
|
||||||
"include_null_values": "Inclure les valeurs nulles"
|
"include_null_values": "Inclure les valeurs nulles",
|
||||||
|
"spec": "Analyseur"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"rfc": "RFC4180",
|
||||||
|
"legacy": "Hérité (Legacy)",
|
||||||
|
"legacy_warning": "Le mode hérité sera supprimé dans une prochaine version."
|
||||||
},
|
},
|
||||||
"placeholder": {
|
"placeholder": {
|
||||||
"columns": "noms de colonnes séparés par des virgules"
|
"columns": "noms de colonnes séparés par des virgules"
|
||||||
@@ -876,6 +885,7 @@
|
|||||||
"once": "envoyer les en-têtes une fois, jusqu'à msg.reset"
|
"once": "envoyer les en-têtes une fois, jusqu'à msg.reset"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
|
"bad_template": "Colonnes du modèle mal formées.",
|
||||||
"csv_js": "Ce noeud ne gère que les chaînes CSV ou les objets js.",
|
"csv_js": "Ce noeud ne gère que les chaînes CSV ou les objets js.",
|
||||||
"obj_csv": "Aucun modèle de colonnes spécifié pour l'objet -> CSV.",
|
"obj_csv": "Aucun modèle de colonnes spécifié pour l'objet -> CSV.",
|
||||||
"bad_csv": "Données CSV mal formées - sortie probablement corrompue."
|
"bad_csv": "Données CSV mal formées - sortie probablement corrompue."
|
||||||
@@ -885,12 +895,14 @@
|
|||||||
"label": {
|
"label": {
|
||||||
"select": "Sélecteur",
|
"select": "Sélecteur",
|
||||||
"output": "Sortie",
|
"output": "Sortie",
|
||||||
"in": "dans"
|
"in": "dans",
|
||||||
|
"prefix": "Nom de la propriété pour le contenu HTML"
|
||||||
},
|
},
|
||||||
"output": {
|
"output": {
|
||||||
"html": "le contenu html des éléments",
|
"html": "le contenu html des éléments",
|
||||||
"text": "uniquement le contenu textuel des éléments",
|
"text": "uniquement le contenu textuel des éléments",
|
||||||
"attr": "un objet de n'importe quel attribut des éléments"
|
"attr": "un objet de n'importe quel attribut des éléments",
|
||||||
|
"compl": "un objet pour tous les attributs de tous les éléments ainsi que du contenu HTML"
|
||||||
},
|
},
|
||||||
"format": {
|
"format": {
|
||||||
"single": "comme un seul message contenant un tableau",
|
"single": "comme un seul message contenant un tableau",
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
avant d'être envoyé.</p>
|
avant d'être envoyé.</p>
|
||||||
<p>Si <code>msg._session</code> n'est pas présent, la charge utile est
|
<p>Si <code>msg._session</code> n'est pas présent, la charge utile est
|
||||||
envoyé à <b>tous</b> les clients connectés.</p>
|
envoyé à <b>tous</b> les clients connectés.</p>
|
||||||
|
<p>En mode Répondre à, définir <code>msg.reset = true</code> réinitialisera la connexion
|
||||||
|
spécifiée par _session.id ou toutes les connexions si aucun _session.id n'est spécifié.</p>
|
||||||
<p><b>Remarque</b> : Sur certains systèmes, vous aurez peut-être besoin d'un accès root ou administrateur
|
<p><b>Remarque</b> : Sur certains systèmes, vous aurez peut-être besoin d'un accès root ou administrateur
|
||||||
pour accéder aux ports inférieurs à 1024.</p>
|
pour accéder aux ports inférieurs à 1024.</p>
|
||||||
</script>
|
</script>
|
||||||
@@ -40,6 +42,8 @@
|
|||||||
caractères renvoyés dans un tampon fixe, correspondant à un caractère spécifié avant de revenir,
|
caractères renvoyés dans un tampon fixe, correspondant à un caractère spécifié avant de revenir,
|
||||||
attendre un délai fixe à partir de la première réponse, puis revenir, s'installer et attender les données, ou envoie puis ferme la connexion
|
attendre un délai fixe à partir de la première réponse, puis revenir, s'installer et attender les données, ou envoie puis ferme la connexion
|
||||||
immédiatement, sans attendre de réponse.</p>
|
immédiatement, sans attendre de réponse.</p>
|
||||||
|
<p>Dans le cas du mode veille (maintien de la connexion), vous pouvez envoyer <code>msg.reset = true</code> ou <code>msg.reset = "host:port"</code> pour forcer une interruption
|
||||||
|
de la connexion et une reconnexion automatique.</p>
|
||||||
<p>La réponse sortira dans <code>msg.payload</code> en tant que tampon, vous pouvez alors utiliser la fonction .toString().</p>
|
<p>La réponse sortira dans <code>msg.payload</code> en tant que tampon, vous pouvez alors utiliser la fonction .toString().</p>
|
||||||
<p>Si vous laissez l'hôte ou le port tcp vide, ils doivent être définis à l'aide des propriétés <code>msg.host</code> et <code>msg.port</code> dans chaque message envoyé au noeud.</ p>
|
<p>Si vous laissez l'hôte ou le port tcp vide, ils doivent être définis à l'aide des propriétés <code>msg.host</code> et <code>msg.port</code> dans chaque message envoyé au noeud.</ p>
|
||||||
</script>
|
</script>
|
||||||
@@ -36,7 +36,9 @@
|
|||||||
</dl>
|
</dl>
|
||||||
<h3>Détails</h3>
|
<h3>Détails</h3>
|
||||||
<p>Le modèle de colonne peut contenir une liste ordonnée de noms de colonnes. Lors de la conversion de CSV en objet, les noms de colonne
|
<p>Le modèle de colonne peut contenir une liste ordonnée de noms de colonnes. Lors de la conversion de CSV en objet, les noms de colonne
|
||||||
seront utilisés comme noms de propriété. Alternativement, les noms de colonne peuvent être tirés de la première ligne du CSV.</p>
|
seront utilisés comme noms de propriété. Alternativement, les noms de colonne peuvent être tirés de la première ligne du CSV.
|
||||||
|
<p>Lorsque l'analyseur RFC est sélectionné, le modèle de colonne doit être conforme à la norme RFC4180.</p>
|
||||||
|
</p>
|
||||||
<p>Lors de la conversion au format CSV, le modèle de colonnes est utilisé pour identifier les propriétés à extraire de l'objet et dans quel ordre.</p>
|
<p>Lors de la conversion au format CSV, le modèle de colonnes est utilisé pour identifier les propriétés à extraire de l'objet et dans quel ordre.</p>
|
||||||
<p>Si le modèle de colonnes est vide, vous pouvez utiliser une simple liste de propriétés séparées par des virgules fournies dans <code>msg.columns</code> pour
|
<p>Si le modèle de colonnes est vide, vous pouvez utiliser une simple liste de propriétés séparées par des virgules fournies dans <code>msg.columns</code> pour
|
||||||
déterminer quoi extraire et dans quel ordre. Si ni l'un ni l'autre n'est présent, toutes les propriétés de l'objet sont sorties dans l'ordre
|
déterminer quoi extraire et dans quel ordre. Si ni l'un ni l'autre n'est présent, toutes les propriétés de l'objet sont sorties dans l'ordre
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ var connections = [];
|
|||||||
const events = require("@node-red/util").events;
|
const events = require("@node-red/util").events;
|
||||||
|
|
||||||
function handleCommsEvent(event) {
|
function handleCommsEvent(event) {
|
||||||
publish(event.topic,event.data,event.retain);
|
publish(event.topic,event.data,event.retain,event.session,event.excludeSession);
|
||||||
}
|
}
|
||||||
function handleStatusEvent(event) {
|
function handleStatusEvent(event) {
|
||||||
if (!event.status) {
|
if (!event.status) {
|
||||||
@@ -74,13 +74,17 @@ function handleEventLog(event) {
|
|||||||
publish("event-log/"+event.id,event.payload||{});
|
publish("event-log/"+event.id,event.payload||{});
|
||||||
}
|
}
|
||||||
|
|
||||||
function publish(topic,data,retain) {
|
function publish(topic, data, retain, session, excludeSession) {
|
||||||
if (retain) {
|
if (retain) {
|
||||||
retained[topic] = data;
|
retained[topic] = data;
|
||||||
} else {
|
} else {
|
||||||
delete retained[topic];
|
delete retained[topic];
|
||||||
}
|
}
|
||||||
connections.forEach(connection => connection.send(topic,data))
|
connections.forEach(connection => {
|
||||||
|
if ((!session || connection.session === session) && (!excludeSession || connection.session !== excludeSession)) {
|
||||||
|
connection.send(topic,data)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +113,10 @@ var api = module.exports = {
|
|||||||
*/
|
*/
|
||||||
addConnection: async function(opts) {
|
addConnection: async function(opts) {
|
||||||
connections.push(opts.client);
|
connections.push(opts.client);
|
||||||
|
events.emit('comms:connection-added', {
|
||||||
|
session: opts.client.session,
|
||||||
|
user: opts.client.user
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,6 +134,9 @@ var api = module.exports = {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
events.emit('comms:connection-removed', {
|
||||||
|
session: opts.client.session
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,5 +168,23 @@ var api = module.exports = {
|
|||||||
* @return {Promise<Object>} - resolves when complete
|
* @return {Promise<Object>} - resolves when complete
|
||||||
* @memberof @node-red/runtime_comms
|
* @memberof @node-red/runtime_comms
|
||||||
*/
|
*/
|
||||||
unsubscribe: async function(opts) {}
|
unsubscribe: async function(opts) {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {CommsConnection} opts.client - the client connection
|
||||||
|
* @param {String} opts.topic - the message topic
|
||||||
|
* @param {String} opts.data - the message data
|
||||||
|
* @return {Promise<Object>} - resolves when complete
|
||||||
|
*/
|
||||||
|
receive: async function (opts) {
|
||||||
|
if (opts.topic) {
|
||||||
|
events.emit('comms:message:' + opts.topic, {
|
||||||
|
session: opts.client.session,
|
||||||
|
user: opts.user,
|
||||||
|
data: opts.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user