Merge branch 'master' into header-border

This commit is contained in:
Mauricio Bonani 2024-07-01 06:14:35 -04:00 committed by GitHub
commit 29058c163a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 145 additions and 102 deletions

View File

@ -182,6 +182,10 @@ function genericStrategy(adminApp,strategy) {
maxAge: null, maxAge: null,
...settings.httpAdminCookieOptions ...settings.httpAdminCookieOptions
} }
if (sessionOptions.cookie.name){
sessionOptions.name = sessionOptions.cookie.name
delete sessionOptions.cookie.name
}
} }
adminApp.use(session(sessionOptions)); adminApp.use(session(sessionOptions));
//TODO: all passport references ought to be in ./auth //TODO: all passport references ought to be in ./auth
@ -217,10 +221,10 @@ function genericStrategy(adminApp,strategy) {
adminApp.get('/auth/strategy', adminApp.get('/auth/strategy',
passport.authenticate(strategy.name, { passport.authenticate(strategy.name, {
session:false, session:false,
failureMessage: true, failWithError: true,
failureRedirect: settings.httpAdminRoot + '?session_message=Login Failed' failureMessage: true
}), }),
completeGenerateStrategyAuth, completeGenericStrategyAuth,
handleStrategyError handleStrategyError
); );
@ -232,14 +236,14 @@ function genericStrategy(adminApp,strategy) {
passport.authenticate(strategy.name, { passport.authenticate(strategy.name, {
session:false, session:false,
failureMessage: true, failureMessage: true,
failureRedirect: settings.httpAdminRoot + '?session_message=Login Failed' failWithError: true
}), }),
completeGenerateStrategyAuth, completeGenericStrategyAuth,
handleStrategyError handleStrategyError
); );
} }
function completeGenerateStrategyAuth(req,res) { function completeGenericStrategyAuth(req,res) {
var tokens = req.user.tokens; var tokens = req.user.tokens;
delete req.user.tokens; delete req.user.tokens;
// Successful authentication, redirect home. // Successful authentication, redirect home.
@ -249,6 +253,8 @@ function handleStrategyError(err, req, res, next) {
if (res.headersSent) { if (res.headersSent) {
return next(err) return next(err)
} }
// Remove the header that passport auto-adds as we don't need it
res.removeHeader('WWW-Authenticate')
log.audit({event: "auth.login.fail.oauth",error:err.toString()}); log.audit({event: "auth.login.fail.oauth",error:err.toString()});
res.redirect(settings.httpAdminRoot + '?session_message='+err.toString()); res.redirect(settings.httpAdminRoot + '?session_message='+err.toString());
} }

View File

@ -27,7 +27,8 @@
"lock": "Verrouiller", "lock": "Verrouiller",
"unlock": "Déverrouiller", "unlock": "Déverrouiller",
"locked": "Verrouillé", "locked": "Verrouillé",
"unlocked": "Déverrouillé" "unlocked": "Déverrouillé",
"format": "Format"
}, },
"type": { "type": {
"string": "chaîne de caractères", "string": "chaîne de caractères",
@ -54,10 +55,10 @@
"workspace": { "workspace": {
"defaultName": "Flux __number__", "defaultName": "Flux __number__",
"editFlow": "Modifier le flux : __name__", "editFlow": "Modifier le flux : __name__",
"confirmDelete": "Confirmation de la suppression", "confirmDelete": "Confirmer la suppression",
"delete": "Etes-vous sûr de vouloir supprimer '__label__'?", "delete": "Êtes-vous sûr de vouloir supprimer '__label__' ?",
"dropFlowHere": "Déposer le flux ici", "dropFlowHere": "Lâchez le flux ici",
"dropImageHere": "Déposer l'image ici", "dropImageHere": "Lâchez l'image ici",
"addFlow": "Ajouter un flux", "addFlow": "Ajouter un flux",
"addFlowToRight": "Ajouter un flux à droite", "addFlowToRight": "Ajouter un flux à droite",
"closeFlow": "Fermer le flux", "closeFlow": "Fermer le flux",
@ -74,7 +75,7 @@
"enabled": "Activé", "enabled": "Activé",
"disabled": "Désactivé", "disabled": "Désactivé",
"info": "Description", "info": "Description",
"selectNodes": "Cliquer sur les noeuds pour sélectionner", "selectNodes": "Cliquer pour sélectionner",
"enableFlow": "Activer le flux", "enableFlow": "Activer le flux",
"disableFlow": "Désactiver le flux", "disableFlow": "Désactiver le flux",
"lockFlow": "Verrouiller le flux", "lockFlow": "Verrouiller le flux",
@ -98,7 +99,7 @@
"rtl": "De droite à gauche", "rtl": "De droite à gauche",
"auto": "Contextuel", "auto": "Contextuel",
"language": "Langue", "language": "Langue",
"browserDefault": "Navigateur par défaut" "browserDefault": "Par défaut du Navigateur"
}, },
"sidebar": { "sidebar": {
"show": "Afficher la barre latérale" "show": "Afficher la barre latérale"
@ -134,7 +135,7 @@
"disableSelectedNodes": "Désactiver les noeuds sélectionnés", "disableSelectedNodes": "Désactiver les noeuds sélectionnés",
"showSelectedNodeLabels": "Afficher les étiquettes des noeuds sélectionnés", "showSelectedNodeLabels": "Afficher les étiquettes des noeuds sélectionnés",
"hideSelectedNodeLabels": "Masquer les étiquettes des noeuds sélectionnés", "hideSelectedNodeLabels": "Masquer les étiquettes des noeuds sélectionnés",
"showWelcomeTours": "Afficher les visites guidées pour les nouvelles versions", "showWelcomeTours": "Afficher les visites guidées des nouvelles versions",
"help": "Site web de Node-RED", "help": "Site web de Node-RED",
"projects": "Projets", "projects": "Projets",
"projects-new": "Nouveau projet", "projects-new": "Nouveau projet",
@ -143,7 +144,7 @@
"showNodeLabelDefault": "Afficher l'étiquette des noeuds nouvellement ajoutés", "showNodeLabelDefault": "Afficher l'étiquette des noeuds nouvellement ajoutés",
"codeEditor": "Éditeur de code", "codeEditor": "Éditeur de code",
"groups": "Groupes", "groups": "Groupes",
"groupSelection": "Grouper cette sélection", "groupSelection": "Grouper la sélection",
"ungroupSelection": "Dégrouper la sélection", "ungroupSelection": "Dégrouper la sélection",
"groupMergeSelection": "Fusionner la sélection", "groupMergeSelection": "Fusionner la sélection",
"groupRemoveSelection": "Supprimer du groupe", "groupRemoveSelection": "Supprimer du groupe",
@ -155,7 +156,7 @@
"alignMiddle": "Aligner au milieu", "alignMiddle": "Aligner au milieu",
"alignBottom": "Aligner en bas", "alignBottom": "Aligner en bas",
"distributeHorizontally": "Répartir horizontalement", "distributeHorizontally": "Répartir horizontalement",
"distributeVertically": "Distribuer verticalement", "distributeVertically": "Répartir verticalement",
"moveToBack": "Déplacer vers l'arrière", "moveToBack": "Déplacer vers l'arrière",
"moveToFront": "Déplacer vers l'avant", "moveToFront": "Déplacer vers l'avant",
"moveBackwards": "Reculer", "moveBackwards": "Reculer",
@ -163,21 +164,21 @@
} }
}, },
"actions": { "actions": {
"toggle-navigator": "Basculer de navigateur", "toggle-navigator": "Basculer l'affichage du navigateur",
"zoom-out": "Dézoomer", "zoom-out": "Réduire",
"zoom-reset": "Réinitialiser le zoom", "zoom-reset": "Réinitialiser",
"zoom-in": "Agrandir", "zoom-in": "Agrandir",
"search-flows": "Rechercher le flux", "search-flows": "Rechercher le flux",
"search-prev": "Précédent", "search-prev": "Précédent",
"search-next": "Suivant", "search-next": "Suivant",
"search-counter": "\"__term__\" __result__ de __count__" "search-counter": "\"__term__\" __result__ sur __count__"
}, },
"user": { "user": {
"loggedInAs": "Connecté en tant que __name__", "loggedInAs": "Connecté en tant que __name__",
"username": "Nom d'utilisateur", "username": "Nom d'utilisateur",
"password": "Mot de passe", "password": "Mot de passe",
"login": "Connexion", "login": "Se connecter",
"loginFailed": "Échec de la connexion", "loginFailed": "Échec de connexion",
"notAuthorized": "Pas autorisé", "notAuthorized": "Pas autorisé",
"errors": { "errors": {
"settings": "Vous devez être connecté pour accéder aux paramètres", "settings": "Vous devez être connecté pour accéder aux paramètres",
@ -193,16 +194,16 @@
"warning": "<strong>Attention</strong> : __message__", "warning": "<strong>Attention</strong> : __message__",
"warnings": { "warnings": {
"undeployedChanges": "Le noeud a des modifications non déployées", "undeployedChanges": "Le noeud a des modifications non déployées",
"nodeActionDisabled": "Actions de noeud désactivées", "nodeActionDisabled": "Les actions du noeud sont désactivées",
"nodeActionDisabledSubflow": "Actions de noeud désactivées dans le sous-flux", "nodeActionDisabledSubflow": "Les actions de noeud sont désactivées à l'intérieur du sous-flux",
"missing-types": "<p>Flux arrêtés en raison de types de noeuds manquants.</p>", "missing-types": "<p>Flux arrêtés en raison de types de noeuds manquants.</p>",
"missing-modules": "<p>Flux arrêtés en raison de modules manquants.</p>", "missing-modules": "<p>Flux arrêtés en raison de modules manquants.</p>",
"safe-mode": "<p>Flux arrêtés en mode sans échec.</p><p>Vous pouvez modifier vos flux et déployer les changements pour redémarrer.</p>", "safe-mode": "<p>Flux arrêtés en mode sans échec.</p><p>Vous pouvez modifier vos flux et déployer ensuite les changements afin de démarrer vos flux.</p>",
"restartRequired": "Node-RED doit être redémarré pour mettre à jour les modules", "restartRequired": "Node-RED doit être redémarré pour mettre à jour les modules",
"credentials_load_failed": "<p>Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.</p><p>Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.</p>", "credentials_load_failed": "<p>Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.</p><p>Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.</p>",
"credentials_load_failed_reset": "<p>Les informations d'identification n'ont pas pu être déchiffrées</p><p>Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.</p><p>Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification de flux existantes seront perdues.</p>", "credentials_load_failed_reset": "<p>Les informations d'identification n'ont pas pu être déchiffrées</p><p>Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.</p><p>Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification des flux existants seront perdues.</p>",
"missing_flow_file": "<p>Fichier contenant les flux introuvable.</p><p>Le projet n'est pas configuré avec un fichier de flux.</p>", "missing_flow_file": "<p>Fichier contenant les flux introuvable.</p><p>Le projet n'est pas configuré avec un fichier de flux.</p>",
"missing_package_file": "<p>Fichier de paquetage du projet introuvable.</p><p>Il manque au projet un fichier package.json.</p>", "missing_package_file": "<p>Fichier de paquetage du projet introuvable.</p><p>Il manque au projet le fichier <code>package.json</code>.</p>",
"project_empty": "<p>Le projet est vide.</p><p>Voulez-vous créer un ensemble de fichiers de projet par défaut ?<br/>Sinon, vous devrez ajouter manuellement des fichiers au projet (en dehors de l'éditeur).</p>", "project_empty": "<p>Le projet est vide.</p><p>Voulez-vous créer un ensemble de fichiers de projet par défaut ?<br/>Sinon, vous devrez ajouter manuellement des fichiers au projet (en dehors de l'éditeur).</p>",
"project_not_found": "<p>Le projet '__project__' est introuvable.</p>", "project_not_found": "<p>Le projet '__project__' est introuvable.</p>",
"git_merge_conflict": "<p>La fusion automatique des modifications a échoué.</p><p>Corriger les conflits non fusionnés, puis valider le résultat.</p>" "git_merge_conflict": "<p>La fusion automatique des modifications a échoué.</p><p>Corriger les conflits non fusionnés, puis valider le résultat.</p>"
@ -219,7 +220,7 @@
}, },
"project": { "project": {
"change-branch": "Changer pour une branche locale '__project__'", "change-branch": "Changer pour une branche locale '__project__'",
"merge-abort": "Git fusion abandonnée", "merge-abort": "Fusion Git abandonnée",
"loaded": "Projet '__project__' chargé", "loaded": "Projet '__project__' chargé",
"updated": "Projet '__project__' mis à jour", "updated": "Projet '__project__' mis à jour",
"pull": "Projet '__project__' rechargé", "pull": "Projet '__project__' rechargé",
@ -352,7 +353,7 @@
"backgroundUpdate": "Les flux sur le serveur ont été mis à jour.", "backgroundUpdate": "Les flux sur le serveur ont été mis à jour.",
"conflictChecking": "Vérifier si les modifications peuvent être fusionnées automatiquement", "conflictChecking": "Vérifier si les modifications peuvent être fusionnées automatiquement",
"conflictAutoMerge": "Les modifications n'incluent aucun conflit et peuvent être fusionnées automatiquement.", "conflictAutoMerge": "Les modifications n'incluent aucun conflit et peuvent être fusionnées automatiquement.",
"conflictManualMerge": "Les changements incluent des conflits qui doivent être résolus avant de pouvoir être déployés.", "conflictManualMerge": "Les modifications incluent des conflits qui doivent être résolus avant de pouvoir être déployées.",
"plusNMore": "+ __count__ en plus" "plusNMore": "+ __count__ en plus"
} }
}, },
@ -372,16 +373,17 @@
"deleted": "supprimé", "deleted": "supprimé",
"flowDeleted": "flux supprimé", "flowDeleted": "flux supprimé",
"flowAdded": "flux ajouté", "flowAdded": "flux ajouté",
"moved": "déplacé",
"movedTo": "déplacé vers __id__", "movedTo": "déplacé vers __id__",
"movedFrom": "déplacé depuis __id__" "movedFrom": "déplacé depuis __id__"
}, },
"nodeCount": "__count__ noeud", "nodeCount": "__count__ noeud",
"nodeCount_plural": "__count__ noeuds", "nodeCount_plural": "__count__ noeuds",
"local": "Changements locaux", "local": "Changements locaux",
"remote": "Modifications à distance", "remote": "Changements distants",
"reviewChanges": "Examiner les modifications", "reviewChanges": "Examiner les modifications",
"noBinaryFileShowed": "Impossible d'afficher le contenu du fichier binaire", "noBinaryFileShowed": "Impossible d'afficher le contenu du fichier binaire",
"viewCommitDiff": "Afficher les modifications de validation", "viewCommitDiff": "Afficher les modifications de la validation",
"compareChanges": "Comparer les modifications", "compareChanges": "Comparer les modifications",
"saveConflict": "Enregistrer la résolution des conflits", "saveConflict": "Enregistrer la résolution des conflits",
"conflictHeader": "<span>__resolved__</span> sur <span>__unresolved__</span> conflit(s) résolu(s)", "conflictHeader": "<span>__resolved__</span> sur <span>__unresolved__</span> conflit(s) résolu(s)",
@ -395,9 +397,9 @@
"edit": "Modifier le modèle du sous-flux", "edit": "Modifier le modèle du sous-flux",
"subflowInstances": "Il existe __count__ instance de ce modèle de sous-flux", "subflowInstances": "Il existe __count__ instance de ce modèle de sous-flux",
"subflowInstances_plural": "Il existe __count__ instances de ce modèle de sous-flux", "subflowInstances_plural": "Il existe __count__ instances de ce modèle de sous-flux",
"editSubflowProperties": "modifier les propriétés", "editSubflowProperties": "Modifier les propriétés",
"input": "Entrées:", "input": "Entrées :",
"output": "Sorties:", "output": "Sorties :",
"status": "Statut du noeud", "status": "Statut du noeud",
"deleteSubflow": "Supprimer le sous-flux", "deleteSubflow": "Supprimer le sous-flux",
"confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?", "confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?",
@ -411,7 +413,7 @@
"version": "Version", "version": "Version",
"versionPlaceholder": "x.y.z", "versionPlaceholder": "x.y.z",
"keys": "Mots clés", "keys": "Mots clés",
"keysPlaceholder": "Mots clés séparés par des virgules", "keysPlaceholder": "Mots clés séparés par une virgule",
"author": "Auteur", "author": "Auteur",
"authorPlaceholder": "Votre nom <email@exemple.com>", "authorPlaceholder": "Votre nom <email@exemple.com>",
"desc": "Description", "desc": "Description",
@ -468,7 +470,7 @@
"select": "sélection", "select": "sélection",
"checkbox": "case à cocher", "checkbox": "case à cocher",
"spinner": "valeurs à défiler", "spinner": "valeurs à défiler",
"none": "aucune", "none": "aucun",
"hidden": "masquer la propriété" "hidden": "masquer la propriété"
}, },
"types": { "types": {
@ -496,7 +498,7 @@
"max": "Maximum" "max": "Maximum"
}, },
"errors": { "errors": {
"scopeChange": "La modification de la portée la rendra indisponible pour les noeuds d'autres flux qui l'utilisent", "scopeChange": "La modification de la portée rendra indisponible ce noeud de configuration aux noeuds d'autres flux qui l'utilisent",
"invalidProperties": "Propriétés invalides :", "invalidProperties": "Propriétés invalides :",
"credentialLoadFailed": "Échec du chargement des identifiants du noeud" "credentialLoadFailed": "Échec du chargement des identifiants du noeud"
} }
@ -510,7 +512,7 @@
"unassigned": "Non attribué", "unassigned": "Non attribué",
"global": "Global", "global": "Global",
"workspace": "Espace de travail", "workspace": "Espace de travail",
"editor": "Boîte de dialogue d'édition", "editor": "Boîte d'édition",
"selectAll": "Tout sélectionner", "selectAll": "Tout sélectionner",
"selectNone": "Ne rien sélectionner", "selectNone": "Ne rien sélectionner",
"selectAllConnected": "Sélectionner tous les éléments connectés", "selectAllConnected": "Sélectionner tous les éléments connectés",
@ -541,7 +543,7 @@
"openLibrary": "Ouvrir la bibliothèque...", "openLibrary": "Ouvrir la bibliothèque...",
"saveToLibrary": "Enregistrer dans la bibliothèque...", "saveToLibrary": "Enregistrer dans la bibliothèque...",
"typeLibrary": "__type__ bibliothèque", "typeLibrary": "__type__ bibliothèque",
"unnamedType": "Innomé __type__", "unnamedType": "Sans nom __type__",
"exportedToLibrary": "Noeuds exportés vers la bibliothèque", "exportedToLibrary": "Noeuds exportés vers la bibliothèque",
"dialogSaveOverwrite": "Une __libraryType__ appelée __libraryName__ existe déjà. Écraser ?", "dialogSaveOverwrite": "Une __libraryType__ appelée __libraryName__ existe déjà. Écraser ?",
"invalidFilename": "Nom de fichier non valide", "invalidFilename": "Nom de fichier non valide",
@ -558,7 +560,7 @@
"noInfo": "Pas d'information disponible", "noInfo": "Pas d'information disponible",
"filter": "Rechercher le noeud", "filter": "Rechercher le noeud",
"search": "Rechercher les modules", "search": "Rechercher les modules",
"addCategory": "Ajouter un nouveau...", "addCategory": "Ajouter une nouvelle...",
"label": { "label": {
"subflows": "Sous-flux", "subflows": "Sous-flux",
"network": "Réseau", "network": "Réseau",
@ -638,7 +640,7 @@
"sortAZ": "A-Z", "sortAZ": "A-Z",
"sortRecent": "Récent", "sortRecent": "Récent",
"more": "+ __count__ en plus", "more": "+ __count__ en plus",
"upload": "Charger le fichier tgz du module", "upload": "Charger le fichier .tgz du module",
"refresh": "Actualiser la liste des modules", "refresh": "Actualiser la liste des modules",
"errors": { "errors": {
"catalogLoadFailed": "<p>Échec du chargement du catalogue de noeuds.</p><p>Vérifier la console du navigateur pour plus d'informations</p>", "catalogLoadFailed": "<p>Échec du chargement du catalogue de noeuds.</p><p>Vérifier la console du navigateur pour plus d'informations</p>",
@ -651,7 +653,7 @@
}, },
"confirm": { "confirm": {
"install": { "install": {
"body": "<p>Installation de '__module__'</p><p>Avant l'installation, veuiller lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.</p>", "body": "<p>Installation de '__module__'</p><p>Avant l'installation, veuillez lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.</p>",
"title": "Installer les noeuds" "title": "Installer les noeuds"
}, },
"remove": { "remove": {
@ -666,7 +668,7 @@
"title": "Mettre à jour les noeuds" "title": "Mettre à jour les noeuds"
}, },
"cannotUpdate": { "cannotUpdate": {
"body": "Une mise à jour pour ce noeud est disponible, mais il n'est pas installé dans un emplacement que le gestionnaire de palette peut mettre à jour.<br/><br/>Veuiller vous référer à la documentation pour savoir comment mettre à jour ce noeud." "body": "Une mise à jour pour ce noeud est disponible, mais il n'est pas installé dans un emplacement que le gestionnaire de palette peut mettre à jour.<br/><br/>Veuillez vous référer à la documentation pour savoir comment mettre à jour ce noeud."
}, },
"button": { "button": {
"review": "Ouvrir la documentation", "review": "Ouvrir la documentation",
@ -708,8 +710,8 @@
"nodeHelp": "Aide sur les noeuds", "nodeHelp": "Aide sur les noeuds",
"none": "Aucun", "none": "Aucun",
"arrayItems": "__count__ éléments", "arrayItems": "__count__ éléments",
"showTips": "Vous pouvez ouvrir les astuces à partir du panneau des paramètres", "showTips": "Vous pouvez afficher les astuces à partir du panneau des paramètres",
"outline": "Plan", "outline": "Contour",
"empty": "Vide", "empty": "Vide",
"globalConfig": "Noeuds de configuration globale", "globalConfig": "Noeuds de configuration globale",
"triggerAction": "Déclencher une action", "triggerAction": "Déclencher une action",
@ -722,7 +724,7 @@
"help": { "help": {
"name": "Aide", "name": "Aide",
"label": "Aide", "label": "Aide",
"search": "Aide à la recherche", "search": "Rechercher l'aide",
"nodeHelp": "Aide sur les noeuds", "nodeHelp": "Aide sur les noeuds",
"showHelp": "Afficher l'aide", "showHelp": "Afficher l'aide",
"showInOutline": "Afficher dans les grandes lignes", "showInOutline": "Afficher dans les grandes lignes",
@ -801,7 +803,7 @@
"branches": "Branches", "branches": "Branches",
"noBranches": "Pas de branche", "noBranches": "Pas de branche",
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la branche locale '__name__' ? Ça ne peut pas être annulé.", "deleteConfirm": "Êtes-vous sûr de vouloir supprimer la branche locale '__name__' ? Ça ne peut pas être annulé.",
"unmergedConfirm": "La branche locale '__name__' contient des modifications non fusionnées qui seront perdues. Etes-vous sûr de vouloir la supprimer?", "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", "deleteUnmergedBranch": "Supprimer la branche non fusionnée",
"gitRemotes": "Git distant", "gitRemotes": "Git distant",
"addRemote": "Ajout distant", "addRemote": "Ajout distant",
@ -845,17 +847,17 @@
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la clé SSH __name__ ? Ça ne peut pas être annulé." "deleteConfirm": "Êtes-vous sûr de vouloir supprimer la clé SSH __name__ ? Ça ne peut pas être annulé."
}, },
"versionControl": { "versionControl": {
"unstagedChanges": "Abandon des changements", "unstagedChanges": "Changements non indexés",
"stagedChanges": "Changement mis en place", "stagedChanges": "Changements indexés",
"unstageChange": "Ne pas mettre en place le changement", "unstageChange": "Annuler l'indexation des changements",
"stageChange": "Mettre en place le changement", "stageChange": "Indexer les changements",
"unstageAllChange": "Ne pas mettre en place tous les changements", "unstageAllChange": "Annuler l'indexation de tous les changements",
"stageAllChange": "Mettre en place tous les changements", "stageAllChange": "Indexer tous les changements",
"commitChanges": "Valider les changements", "commitChanges": "Valider les changements",
"resolveConflicts": "Résoudre les conflits", "resolveConflicts": "Résoudre les conflits",
"head": "En-tête", "head": "En-tête",
"staged": "Mis en place", "staged": "Indexé",
"unstaged": "Non mis en place", "unstaged": "Non indexé",
"local": "Local", "local": "Local",
"remote": "Distant", "remote": "Distant",
"revert": "Voulez-vous vraiment annuler les modifications apportées à '__file__' ? Ça ne peut pas être annulé.", "revert": "Voulez-vous vraiment annuler les modifications apportées à '__file__' ? Ça ne peut pas être annulé.",
@ -889,11 +891,11 @@
"pushFailed": "L'envoi a échoué car la branche a des validations plus récentes. Tirer et fusionner d'abord, puis envoyer à nouveau.", "pushFailed": "L'envoi a échoué car la branche a des validations plus récentes. Tirer et fusionner d'abord, puis envoyer à nouveau.",
"push": "Envoyer", "push": "Envoyer",
"pull": "Tirer", "pull": "Tirer",
"unablePull": "<p>Impossible d'extraire les modifications à distance ; vos modifications locales non mises en place seraient écrasées.</p><p>Valider vos modifications et réessayer.</p>", "unablePull": "<p>Impossible d'extraire les modifications à distance; vos modifications locales non mises en place seraient écrasées.</p><p>Valider vos modifications et réessayer.</p>",
"showUnstagedChanges": "Afficher les modifications non mise en place", "showUnstagedChanges": "Afficher les modifications non indexées",
"connectionFailed": "Impossible de se connecter au référentiel distant: ", "connectionFailed": "Impossible de se connecter au référentiel distant: ",
"pullUnrelatedHistory": "<p>Le réferentiel distant a un historique de validations sans rapport.</p><p>Êtes-vous sûr de vouloir extraire les modifications dans votre référentiel local ?</p>", "pullUnrelatedHistory": "<p>Le réferentiel distant a un historique de validations sans rapport.</p><p>Êtes-vous sûr de vouloir extraire les modifications dans votre référentiel local ?</p>",
"pullChanges": "Tirer les changements", "pullChanges": "Tirer les changements distants",
"history": "Historique", "history": "Historique",
"projectHistory": "Historique du projet", "projectHistory": "Historique du projet",
"daysAgo": "il y a __count__ jour", "daysAgo": "il y a __count__ jour",
@ -974,7 +976,7 @@
"result": "Résultat", "result": "Résultat",
"format": "Format", "format": "Format",
"compatMode": "Mode de compatibilité activé", "compatMode": "Mode de compatibilité activé",
"compatModeDesc": "<h3>Mode de compatibilité JSONata</h3><p> L'expression actuelle semble toujours faire référence à <code>msg</code> et sera donc évaluée en mode de compatibilité. Veuiller mettre à jour l'expression pour ne pas utiliser <code>msg</code> car ce mode sera supprimé à l'avenir.</p><p> Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet <code>msg</code>. Par exemple, <code>msg.payload</code> serait utilisé pour accéder à la charge utile.</p><p> Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement <code>charge utile</code>.</p>", "compatModeDesc": "<h3>Mode de compatibilité JSONata</h3><p> L'expression actuelle semble toujours faire référence à <code>msg</code> et sera donc évaluée en mode de compatibilité. Veuillez mettre à jour l'expression pour ne pas utiliser <code>msg</code> car ce mode sera supprimé à l'avenir.</p><p> Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet <code>msg</code>. Par exemple, <code>msg.payload</code> serait utilisé pour accéder à la charge utile.</p><p> Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement <code>charge utile</code>.</p>",
"noMatch": "Aucun résultat correspondant", "noMatch": "Aucun résultat correspondant",
"errors": { "errors": {
"invalid-expr": "Expression JSONata non valide :\n __message__", "invalid-expr": "Expression JSONata non valide :\n __message__",
@ -997,7 +999,7 @@
}, },
"jsonEditor": { "jsonEditor": {
"title": "Éditeur JSON", "title": "Éditeur JSON",
"format": "Format JSON", "format": "Formatter JSON",
"rawMode": "Modifier JSON", "rawMode": "Modifier JSON",
"uiMode": "Afficher l'éditeur", "uiMode": "Afficher l'éditeur",
"rawMode-readonly": "JSON", "rawMode-readonly": "JSON",
@ -1016,7 +1018,7 @@
"markdownEditor": { "markdownEditor": {
"title": "Éditeur Markdown", "title": "Éditeur Markdown",
"expand": "Développer", "expand": "Développer",
"format": "Formaté avec Markdown", "format": "Formatter avec Markdown",
"heading1": "Rubrique 1", "heading1": "Rubrique 1",
"heading2": "Rubrique 2", "heading2": "Rubrique 2",
"heading3": "Rubrique 3", "heading3": "Rubrique 3",
@ -1090,7 +1092,7 @@
"credential-key": "Clé de chiffrement des identifiants", "credential-key": "Clé de chiffrement des identifiants",
"cant-get-ssh-key": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.", "cant-get-ssh-key": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.",
"already-exists2": "Existe déjà", "already-exists2": "Existe déjà",
"git-error": "Erreur git", "git-error": "Erreur Git",
"connection-failed": "La connexion a échoué", "connection-failed": "La connexion a échoué",
"not-git-repo": "Ce n'est pas un dépôt Git", "not-git-repo": "Ce n'est pas un dépôt Git",
"repo-not-found": "Référentiel introuvable" "repo-not-found": "Référentiel introuvable"
@ -1104,7 +1106,7 @@
"credentials-file": "Fichier d'identifiants" "credentials-file": "Fichier d'identifiants"
}, },
"encryption-config": { "encryption-config": {
"setup": "Configuration du chiffrage de votre fichier d'informations d'identification", "setup": "Configuration du chiffrement de votre fichier d'informations d'identification",
"desc0": "Votre fichier d'informations d'identification de flux peut être chiffré pour sécuriser son contenu.", "desc0": "Votre fichier d'informations d'identification de flux peut être chiffré pour sécuriser son contenu.",
"desc1": "Si vous souhaitez stocker ces identifiants dans un référentiel Git public, vous devez les chiffrer en fournissant une phrase clé secrète.", "desc1": "Si vous souhaitez stocker ces identifiants dans un référentiel Git public, vous devez les chiffrer en fournissant une phrase clé secrète.",
"desc2": "Votre fichier d'identifiants de flux n'est actuellement pas chiffré.", "desc2": "Votre fichier d'identifiants de flux n'est actuellement pas chiffré.",
@ -1161,9 +1163,9 @@
"add-ssh-key": "Ajouter une clé ssh", "add-ssh-key": "Ajouter une clé ssh",
"credentials-encryption-key": "Clé de chiffrement des identifiants", "credentials-encryption-key": "Clé de chiffrement des identifiants",
"already-exists-2": "Existe déjà", "already-exists-2": "Existe déjà",
"git-error": "Erreur git", "git-error": "Erreur Git",
"con-failed": "La connexion a échoué", "con-failed": "La connexion a échoué",
"not-git": "Ce n'est pas un dépôt git", "not-git": "Ce n'est pas un dépôt Git",
"no-resource": "Référentiel introuvable", "no-resource": "Référentiel introuvable",
"cant-get-ssh-key-path": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.", "cant-get-ssh-key-path": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.",
"unexpected_error": "Erreur inattendue", "unexpected_error": "Erreur inattendue",
@ -1201,7 +1203,7 @@
}, },
"errors": { "errors": {
"no-username-email": "Votre client Git n'est pas configuré avec un nom d'utilisateur/e-mail.", "no-username-email": "Votre client Git n'est pas configuré avec un nom d'utilisateur/e-mail.",
"unexpected": "Une erreur inattendue est apparue", "unexpected": "Une erreur inattendue est survenue",
"code": "Code" "code": "Code"
} }
}, },
@ -1270,7 +1272,7 @@
"list-modified-nodes": "Afficher les flux modifiés", "list-modified-nodes": "Afficher les flux modifiés",
"list-hidden-flows": "Afficher les flux cachés", "list-hidden-flows": "Afficher les flux cachés",
"list-flows": "Lister les flux", "list-flows": "Lister les flux",
"list-subflows": "Liste les sous-flux", "list-subflows": "Lister les sous-flux",
"go-to-previous-location": "Aller à l'emplacement précédent", "go-to-previous-location": "Aller à l'emplacement précédent",
"go-to-next-location": "Aller à l'emplacement suivant", "go-to-next-location": "Aller à l'emplacement suivant",
"copy-selection-to-internal-clipboard": "Copier la sélection dans le presse-papiers", "copy-selection-to-internal-clipboard": "Copier la sélection dans le presse-papiers",
@ -1330,8 +1332,8 @@
"align-selection-to-bottom": "Aligner la sélection vers le bas", "align-selection-to-bottom": "Aligner la sélection vers le bas",
"align-selection-to-middle": "Aligner la sélection au centre verticalement", "align-selection-to-middle": "Aligner la sélection au centre verticalement",
"align-selection-to-center": "Aligner la sélection au centre horizontalement", "align-selection-to-center": "Aligner la sélection au centre horizontalement",
"distribute-selection-horizontally": "Distribuer la sélection horizontalement", "distribute-selection-horizontally": "Répartir la sélection horizontalement",
"distribute-selection-vertical": "Distribuer la sélection verticalement", "distribute-selection-vertical": "Répartir la sélection verticalement",
"wire-series-of-nodes": "Connecter les noeuds en série", "wire-series-of-nodes": "Connecter les noeuds en série",
"wire-node-to-multiple": "Connecter les noeuds à plusieurs", "wire-node-to-multiple": "Connecter les noeuds à plusieurs",
"wire-multiple-to-node": "Connecter plusieurs au noeud", "wire-multiple-to-node": "Connecter plusieurs au noeud",

View File

@ -157,6 +157,12 @@ RED.editor = (function() {
} }
} }
if (valid && "validate" in definition[property]) { if (valid && "validate" in definition[property]) {
if (definition[property].hasOwnProperty("required") &&
definition[property].required === false) {
if (value === "") {
return true;
}
}
try { try {
var opt = {}; var opt = {};
if (label) { if (label) {
@ -183,6 +189,11 @@ RED.editor = (function() {
}); });
} }
} else if (valid) { } else if (valid) {
if (definition[property].hasOwnProperty("required") && definition[property].required === false) {
if (value === "") {
return true;
}
}
// If the validator is not provided in node property => Check if the input has a validator // If the validator is not provided in node property => Check if the input has a validator
if ("category" in node._def) { if ("category" in node._def) {
const isConfig = node._def.category === "config"; const isConfig = node._def.category === "config";

View File

@ -165,7 +165,13 @@ RED.editor.codeEditor.monaco = (function() {
//Handles orphaned models //Handles orphaned models
//ensure loaded models that are not explicitly destroyed by a call to .destroy() are disposed //ensure loaded models that are not explicitly destroyed by a call to .destroy() are disposed
RED.events.on("editor:close",function() { RED.events.on("editor:close",function() {
let models = window.monaco ? monaco.editor.getModels() : null; if (!window.monaco) { return; }
const editors = window.monaco.editor.getEditors()
const orphanEditors = editors.filter(editor => editor && !document.body.contains(editor.getDomNode()))
orphanEditors.forEach(editor => {
editor.dispose();
});
let models = monaco.editor.getModels()
if(models && models.length) { if(models && models.length) {
console.warn("Cleaning up monaco models left behind. Any node that calls createEditor() should call .destroy().") console.warn("Cleaning up monaco models left behind. Any node that calls createEditor() should call .destroy().")
for (let index = 0; index < models.length; index++) { for (let index = 0; index < models.length; index++) {
@ -1124,6 +1130,7 @@ RED.editor.codeEditor.monaco = (function() {
$(el).remove(); $(el).remove();
$(toolbarRow).remove(); $(toolbarRow).remove();
ed.dispose();
} }
ed.resize = function resize() { ed.resize = function resize() {

View File

@ -11,9 +11,22 @@ RED.editor.mermaid = (function () {
if (!initializing) { if (!initializing) {
initializing = true initializing = true
$.getScript( // Find the cache-buster:
'vendor/mermaid/mermaid.min.js', let cacheBuster
function (data, stat, jqxhr) { $('script').each(function (i, el) {
if (!cacheBuster) {
const src = el.getAttribute('src')
const m = /\?v=(.+)$/.exec(src)
if (m) {
cacheBuster = m[1]
}
}
})
$.ajax({
url: `vendor/mermaid/mermaid.min.js?v=${cacheBuster}`,
dataType: "script",
cache: true,
success: function (data, stat, jqxhr) {
mermaid.initialize({ mermaid.initialize({
startOnLoad: false, startOnLoad: false,
theme: RED.settings.get('mermaid', {}).theme theme: RED.settings.get('mermaid', {}).theme
@ -24,7 +37,7 @@ RED.editor.mermaid = (function () {
render(pending) render(pending)
} }
} }
) });
} }
} else { } else {
const nodes = document.querySelectorAll(selector) const nodes = document.querySelectorAll(selector)

View File

@ -23,14 +23,16 @@ module.exports = {
if (existingSessionId) { if (existingSessionId) {
connections.delete(opts.session) connections.delete(opts.session)
const session = sessions.get(existingSessionId) const session = sessions.get(existingSessionId)
session.active = false if (session) {
session.idleTimeout = setTimeout(() => { session.active = false
sessions.delete(existingSessionId) session.idleTimeout = setTimeout(() => {
}, 30000) sessions.delete(existingSessionId)
runtime.events.emit('comms', { }, 30000)
topic: "multiplayer/connection-removed", runtime.events.emit('comms', {
data: { session: existingSessionId } topic: "multiplayer/connection-removed",
}) data: { session: existingSessionId }
})
}
} }
}) })
runtime.events.on('comms:message:multiplayer/connect', (opts) => { runtime.events.on('comms:message:multiplayer/connect', (opts) => {
@ -91,29 +93,31 @@ module.exports = {
const sessionId = connections.get(opts.session) const sessionId = connections.get(opts.session)
const session = sessions.get(sessionId) const session = sessions.get(sessionId)
if (opts.user) { if (session) {
if (session.user.anonymous !== opts.user.anonymous) { if (opts.user) {
session.user = opts.user if (session.user.anonymous !== opts.user.anonymous) {
runtime.events.emit('comms', { session.user = opts.user
topic: 'multiplayer/connection-added', runtime.events.emit('comms', {
excludeSession: opts.session, topic: 'multiplayer/connection-added',
data: session excludeSession: opts.session,
}) data: session
})
}
} }
}
session.location = opts.data session.location = opts.data
const payload = { const payload = {
session: sessionId, session: sessionId,
workspace: opts.data.workspace, workspace: opts.data.workspace,
node: opts.data.node node: opts.data.node
}
runtime.events.emit('comms', {
topic: 'multiplayer/location',
data: payload,
excludeSession: opts.session
})
} }
runtime.events.emit('comms', {
topic: 'multiplayer/location',
data: payload,
excludeSession: opts.session
})
}) })
} }
} }