diff --git a/README.md b/README.md index f83adc595076495ab84c0fa8ce4d2a00adcb2380..44dcce44c0767492d80519dfc8380dc1db7f99c0 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,22 @@ Duniter graphical interface. This is a developement package which is embedded in > Requires [Yarn](https://classic.yarnpkg.com/en/docs/install/) ```bash +npm i -g nvm yarn bower +bower install nvm install 9 nvm use 9 -yarn +yarn --pure-lockfile ``` ## Run ```bash -node run.js direct_webstart +firefox http://localhost:9220 & +yarn run webstart +``` + +## Dev server with hot reload on file save +```bash +firefox http://localhost:9220 & +yarn run start ``` diff --git a/app/js/lib/conf/i18n/en.json b/app/js/lib/conf/i18n/en.json index 92a6fe2d4b7b0c355bc4c32a0fd0bc5c11a23003..eb5e6e6fa585b14d09f1eba9afe1539a7f67171d 100644 --- a/app/js/lib/conf/i18n/en.json +++ b/app/js/lib/conf/i18n/en.json @@ -129,6 +129,7 @@ "home.current.medianTime": "Median time", "home.current.powMin": "Common difficulty level", "home.current.mmass": "Monetary mass", + "home.current.mmass_kud": "Monetary mass in thousands universal dividend (kilo UD)", "home.pulling.network": "Network", "home.pulling.peer": "Peer", "home.pulling.state.unkown": "Next sync in few minutes", diff --git a/app/js/lib/conf/i18n/fr.json b/app/js/lib/conf/i18n/fr.json new file mode 100644 index 0000000000000000000000000000000000000000..f91c5ddefa23d5df1cbd853d47ac2e4c2490d3ea --- /dev/null +++ b/app/js/lib/conf/i18n/fr.json @@ -0,0 +1,259 @@ +{ + "top.menu.overview": "Accueil", + "top.menu.data": "Explorer", + "top.menu.settings": "Paramètres", + "top.menu.wallet": "Porte-feuilles", + "general.server.started": "Server démarré", + "general.server.stopped": "Server arrêté", + "general.choose_option": "Choisissez votre option", + "general.network.reconf_ok": "Reconfiguration réussie", + "global.button.validate": "Valider", + "global.button.start": "Démarrer", + "err.unknown": "Erreur inconnue", + "err.connection": "Impossible de se connecter au noeud", + "err.back_index": "Retourner à l'écran précédent", + "err.sync.interrupted": "La syncronisation a échoué en raison de l'erreur suivante:", + "index.message.loading": "Chargement...", + "crypto.secret_key": "Clé secrète", + "index.message.current_block": "Block courant {{ number }}", + "configuration.init.choose.title": "Initialisation", + "configuration.init.choose.message": "Your software has to be initialized. You may either connect to an existing one or restore a backup file.", + "configuration.init.choose.create": "Créer une nouvelle monnaie", + "configuration.init.choose.connect": "Se connecter à une monnaie existante", + "configuration.init.choose.import": "Importer depuis un fichier de sauvegarde", + "configuration.create_currency.cancel": "Annuler et retourner à l'accueil", + "configuration.create_uid.title": "Votre identité", + "configuration.create_uid.message": "As a first step, you need to define your personal, unique identity.<br/>The following informations will be <strong>definitive</strong> for this currency: please choose them carefully.", + "configuration.create_uid.uid.tooltip": "The name you will be known as.", + "configuration.create_uid.entropy.tooltip": "An entropy source to make your clé unique: an e-mail, a phone n°, ...", + "configuration.create_uid.password.tooltip": "A secret password to protect your clé.", + "configuration.create_uid.create_button": "Continue", + "configuration.create_uid.preview_button": "Preview pubkey", + "configuration.create_uid.nrp_algo_choose": "NRP algorithm", + "configuration.create_uid.nrp_algo_choose_1": "N = 4096 ; r = 16 ; p = 1", + "configuration.create_uid.modal_title": "Identity confirmation", + "configuration.create_uid.modal_message": "This identity will be definitive for this currency: you will be known by your User ID and will be able to access your account using your Secret Clé and Password values.", + "configuration.create_uid.modal_agree": "Agree", + "configuration.create_uid.modal_disagree": "Disagree", + "configuration.create_uid.modal_preview_title": "Preview of pubkey", + "configuration.create_uid.modal_preview_ok": "OK", + "configuration.ws2p.private": "Enable WS2P Private access", + "configuration.ws2p.private.desc": "<b>Strongly recommanded</b>. <i>No configuration required</i>. Private WS2P access allows your noeud to connect through P2P to other noeuds without exposing itself to the Internet. This is the most secure and efficient way to connect your noeud to the réseau.", + "configuration.ws2p.private.connections.title": "Connections", + "configuration.ws2p.private.connections.message": "You can limit the number of active private connections.", + "configuration.ws2p.private.max": "Maximum", + "configuration.proxiesConf.title": "Setting up a Proxy", + "configuration.proxiesConf.proxySocksAddress": "Classical socks proxy", + "configuration.proxiesConf.torMessage": "<b>Aversissement :</b> If you want to use a socks proxy to redirect all outgoing traffic via <b>Tor</b>, you must use the <i>\"Tor socks proxy\"</i> field :", + "configuration.proxiesConf.proxyTorAddress": "Tor socks proxy", + "configuration.proxiesConf.clear": "clear", + "configuration.proxiesConf.tor": "tor", + "configuration.proxiesConf.none": "none", + "configuration.proxiesConf.reachingClearEp": "How do you want to reach the classic noeuds ? (clear endpoints)", + "configuration.ws2p.public": "Enable WS2P Public access", + "configuration.ws2p.public.desc": "<b>Recommanded</b>. Public WS2P access allows your noeud to be publicly visible to communicate through WS2P. Considering that most of the noeuds will communicate through WS2P access, it is important to have a maximum number of noeuds with Public WS2P access enabled to have a decentralized réseau.", + "configuration.ws2p.public.upnp.title": "UPnP", + "configuration.ws2p.public.upnp.message": "Automated configuration. You need to have a box (router) for this to work. Typically true if you use Duniter at home.", + "configuration.ws2p.public.upnp.value": "Enable Public WS2P accss through UPnP", + "configuration.ws2p.public.manual.title": "Manual configuration", + "configuration.ws2p.public.manual.message": "You can also manually configure your noeud for Public WS2P access.", + "configuration.ws2p.public.manual.local_ipv4": "Private (computer)", + "configuration.ws2p.public.manual.host": "Public (remote host)", + "configuration.ws2p.public.manual.lport": "Private port", + "configuration.ws2p.public.manual.rport": "Public port", + "configuration.ws2p.public.manual.rpath": "WebSocket web path", + "configuration.ws2p.public.connections.title": "Connections", + "configuration.ws2p.public.connections.message": "You can limit the number of active public connections.", + "configuration.ws2p.public.max": "Maximum", + "configuration.create_réseau.desc": "<b>Deprecated</b>. BMA is the legacy communication interface for Duniter noeuds. It is being deprecated. Yet, you can activate it if you know what you are doing.", + "configuration.create_réseau.title": "Réseau", + "configuration.create_réseau.message": "Duniter is a P2P software and needs bidirectionnal access to the réseau. Please chose carefully the following parameters.", + "configuration.create_réseau.none": "None", + "configuration.create_réseau.ipv4.title": "IPv4", + "configuration.create_réseau.ipv6.title": "IPv6", + "configuration.create_réseau.ipv4.message": "For compatibilty reasons, you may prefer to use classic IPv4 interfaces. The configuration is more complicated.", + "configuration.create_réseau.local_ipv4": "Private (computer)", + "configuration.create_réseau.remote_ipv4": "Public (box/router)", + "configuration.create_réseau.local_ipv6": "IPv6", + "configuration.create_réseau.lport": "Local port", + "configuration.create_réseau.rport": "Remote port", + "configuration.create_réseau.port.title": "Ports", + "configuration.create_réseau.ipv6.message": "IPv6 gives your computer a unique, direct address to your noeud over the Internet. This is the <b>recommended way</b> to connect your noeud to the réseau.", + "configuration.create_réseau.port.message": "Wether you use IPv6 or IPv4, Duniter noeud will use this port number for connection to the réseau. If you use IPv6, local and remote port should equal each other.", + "configuration.create_réseau.dns.title": "Domain name", + "configuration.create_réseau.dns": "Domain name", + "configuration.create_réseau.dns.message": "IPv6 (AAAA) and IPv4 (A) DNS records will be used.", + "configuration.create_réseau.upnp": "Use UPnP", + "configuration.create_réseau.bma": "Enable BMA access", + "configuration.create_réseau.button.validate": "Continue", + "configuration.create_réseau.button.autoconf": "Automatic configuration", + "configuration.create_parameters.title": "Currency", + "configuration.create_parameters.message": "Initial parameters of the currency. It should be carefully chosen, as these parameters never change once the currency is started.", + "configuration.create_parameters.currency.title": "Money units", + "configuration.create_parameters.currency.message": "Give a name to your currency. The 3 following parameters configure the way new money units are created.", + "configuration.create_parameters.currency": "Currency name", + "configuration.create_parameters.c": "c", + "configuration.create_parameters.dt": "UD period", + "configuration.create_parameters.ud0": "UD(0)", + "configuration.create_parameters.button.validate": "Continue", + "configuration.create_parameters.wot.title": "Web of Trust", + "configuration.create_parameters.wot.message": "The following parameters deal with identities and their links gathered in the Web of Trust concept.", + "configuration.create_parameters.sigStock": "Max cert stock", + "configuration.create_parameters.sigPeriod": "Delay between 2 certs", + "configuration.create_parameters.sigValidity": "Cert expiry delay", + "configuration.create_parameters.msValidity": "Membership expiry delay", + "configuration.create_parameters.sigQty": "Min required certs", + "configuration.create_parameters.sigWindow": "Cert time window", + "configuration.create_parameters.stepMax": "Max distance", + "configuration.create_parameters.xpercent": "Percent of distance", + "configuration.create_parameters.blockchain.title": "Blockchain", + "configuration.create_parameters.blockchain.message": "The technical support of money and identities is the blockchain. It also has some parameters driving its behavior.", + "configuration.create_parameters.medianTimeBlocks": "Blocks count", + "configuration.create_parameters.avgGenTime": "Block gen. duration", + "configuration.create_parameters.dtDiffEval": "Blocks count for diff.", + "configuration.create_parameters.blocksRot": "Personal diff. blocks", + "configuration.create_parameters.percentRot": "Personal diff. rotation", + "configuration.create_root.title": "Root block creation", + "configuration.create_root.message": "This is the final step to create the new currency! The root block or <i>genesis</i> will include the first members and define the currency parameters. Once generated and submitted, the blockchain will be started.", + "configuration.create_root.button.start": "Start HTTP", + "configuration.create_root.button.stop": "Stop HTTP", + "configuration.create_root.button.generate": "Give a try", + "configuration.create_root.need_a_try": "You need to generate a first block with the « Give a try » button. Start HTTP server to do so.", + "configuration.create_root.button.accept_and_send": "Accept this block and start currency", + "configuration.create_root.button.cancel": "Cancel creation and go to home screen", + "configuration.create_root.host_listening": "Host listening at:", + "configuration.create_uid.pubkey_preview": "Public clé preview", + "home.ws2p_peers": "Pairs connectés", + "home.current.number": "Block courant #", + "home.current.membersCount": "Nombre de membres", + "home.current.medianTime": "Temps médian", + "home.current.powMin": "Niveau de difficulté commune", + "home.current.mmass": "Masse monétaire", + "home.current.mmass_kud": "Masse monétaire en milliers de dividendes universel (kilo DU)", + "home.pulling.network": "Réseau", + "home.pulling.peer": "Pairs", + "home.pulling.state.unkown": "Prochaine syncro dans quelques minutes", + "home.pulling.state.synced": "Syncronisé", + "home.pulling.state.syncing": "En syncronisation...", + "home.pow.unit": "blocks produits par cette clé (2 derniers mois)", + "home.pow.is_mirror": "Ce noeud est un miroir", + "home.pow.is_waiting": "Waiting for better proof conditions", + "home.tabs.overview": "Tableau de bord", + "home.tabs.overview.should_reconfigure": "Your configuration has changed and your noeud is no more reachable from the réseau. You should reconfigure it to have a functional noeud. If this message appears again, you should manually configure the réseau settings. Often, selecting only IPv6 interface (disabling IPv4) solves the problem.", + "home.tabs.network": "Pairs", + "home.tabs.network.button.update": "Check pairs again", + "home.tabs.connections": "Réseau", + "home.tabs.connections.title.connections": "WS2P Connections", + "home.tabs.connections.title.network": "Réseau view", + "home.tabs.connections.legend.title": "Legend", + "home.tabs.connections.legend.prefered": "Prefered: noeuds that you prefer for outcoming connections", + "home.tabs.connections.legend.privileged": "Privileged: noeuds that you privilege the incoming connections (= invitation)", + "home.tabs.logs": "Logs", + "home.tabs.logs.follow.logs": "Suivre les logs", + "home.tabs.logs.pause.logs": "Mettre en pause les logs", + "home.tabs.logs.level.error": "Error", + "home.tabs.logs.level.warn": "Aversissement", + "home.tabs.logs.level.info": "Info", + "home.tabs.logs.level.debug": "Debug", + "home.tabs.logs.level.trace": "Trace", + "sync.title": "Synchroniser", + "sync.message": "Votre noeud will be synchronized with an existing currency: just enter technical details about a noeud to sync with it.", + "sync.host": "Hôte", + "sync.port": "Port", + "sync.check": "Vérifier le noeud", + "sync.start": "Synchroniser avec ce noeud", + "sync.failed": "Synchronisation échouée.", + "sync.mode.simplified": "Mode simplifié", + "sync.mode.manual": "Model manuel", + "sync.simplified.choose": "Noeud auquel se connecter", + "sync.simplified.default_option": "Sélectionnez un noeud pour continuer", + "sync.simplified.currency": "Currency", + "sync.simplified.main_mirror": "(main mirror)", + "sync.simplified.other mirror": "(other mirror)", + "sync.ready.node.part1": "This noeud is available!", + "sync.ready.node.part2": "Click on the green button to proceed.", + "sync.started.node": "Synchronization started on noeud:", + "sync.error.unreachable.try.another.node": "This noeud is not available. Please select another one.", + "home.menu.server.stop": "Arrêter le serveur", + "home.menu.server.start": "Démarrer le serveur", + "home.menu.server.restart": "Redémarrer le serveur", + "home.state": "Server:", + "home.state.started": "STARTED", + "home.state.stopped": "STOPPED", + "settings.tabs.logs": "Logs", + "settings.tabs.data": "Data", + "settings.tabs.backup": "Backup", + "settings.tabs.identity": "Crypto", + "settings.tabs.network": "Réseau", + "settings.tabs.currency": "Currency", + "settings.tabs.cpu": "CPU", + "settings.tabs.modules": "Modules", + "settings.data.reset.title": "Reset this noeud", + "settings.data.reset.message": "If you desire to reset this noeud's data and sync it again with the réseau, please select a noeud to sync against and validate.", + "settings.data.reset.aversissement": "This process <strong>will not</strong> reset the noeud identity and réseau settings, which will be reused.", + "settings.data.reset.peer.none_option": "Select a noeud", + "settings.data.reset.peer.label": "Synchronization peer", + "settings.data.reset.button": "Full reset of the noeud", + "settings.data.reset_sync.button": "Reset data and start sync", + "settings.logs.title": "Logs", + "settings.logs.consult.message": "Your noeud continually generates information messages in a log file. This information may help you understand what your noeud <i>is doing</i> or what it <i>has done</i> few times ago.", + "settings.logs.consult.button": "View real-time logs", + "settings.logs.share.message": "You may want to <b>share your logs</b> with other people, sometimes to get help or to add informations in a bug tracker. Clicking on below button will extract the last 2000 lines of your logs and push it on the web, returning you a link to be shared with whoever you want.", + "settings.logs.share.button": "Create a web link to your logs", + "settings.logs.share.generating": "Generating your link...", + "settings.logs.share.error": "An error occurred during the generation of your link:", + "settings.data.backup.title": "Backup", + "settings.data.backup.message": "You can create backups of your noeud's data and restore them using the buttons below.", + "settings.data.backup.aversissement": "<b>Export</b> will only backup your noeud's data, which <i>excludes your secret clé and configuration details</i>.<br><b>Import</b> will reset your noeud's data by applying the backup. Your secret keys and configuration remains untouched.", + "settings.data.backup.button.export": "Create a data backup", + "settings.data.backup.button.import": "Import a data backup", + "settings.data.backup.importing": "Importing data...", + "settings.data.backup.imported": "Import successfull!", + "settings.network.button.validate": "Save and apply réseau settings", + "settings.network.saved": "Configuration saved and applied successfully", + "settings.key.title": "Public clé of this noeud:", + "settings.key.button.validate": "Save and use this clé", + "settings.key.button.change": "Change keyring", + "settings.key.pubkey.description": "This public clé is the public part of your keyring, which is composed of a public clé and a private clé. This public clé is shared with all the pairs of the réseau and users of the currency, while your private clé is secretely kept and used by this noeud to process operations on the réseau.", + "settings.data.modal_title": "Confirm full reset", + "settings.data.modal_message": "This action will completely reset the data of your noeud and redirect you to initial configuration screen. Do you confirm?", + "settings.data.modal_disagree": "No, cancel this", + "settings.data.modal_agree": "Yes, process the reset", + "settings.data.reset.experimental": "This functionality is still considered experimental. If you encounters strange behaviors, please stop the software and reset manually your noeud by removing all the files BUT conf.json under ~/.config/duniter/duniter_default, and restart the software.", + "settings.cpu.title": "CPU settings", + "settings.cpu.message": "You can adjust the CPU power dedicated to proof-of-work computation. The higher the value, the faster is your noeud, the higher the chances you have to compute a block early.", + "settings.cpu.aversissement": "<b>Up to 8 cores</b> of your machine are dedicated to proof-of-work computation currently. Also, setting CPU to 100% does not mean Duniter will use 100% of each core, but will use as much as possible each of them, as a core is also shared with other programs.", + "settings.cpu.range": "% of CPU power core dedicated to proof-of-work :", + "settings.cpu.power": "Core power:", + "settings.cpu.saved": "CPU settings saved.", + "settings.modules.title": "Modules", + "settings.modules.message": "You can install extensions to your Duniter noeud to provide new features. These extensions are called <b>Duniter modules</b>.", + "settings.modules.no_access": "This instance does not have enough system rights to install new modules on disk.", + "settings.modules.install": "Install this module", + "settings.modules.already_install": "Module already installed", + "settings.modules.path_does_not_exist": "Path does not lead to a module", + "settings.modules.wrong_package_source": "Package URL has wrong format", + "settings.modules.aversissement": "Please be <b>VERY CAREFUL</b> when installing a module: you should <b>check that it is not a virus</b>, nor wants to steal your informations. <b>A MODULE HAS A LOT OF POWER</b> and can access/modify any part of your system (including your private clé), in the limit of the user's access rights.", + "settings.modules.aversissement_light": "AVERSISSEMENT! (click to see more)", + "settings.modules.aversissement_close": "Close this message", + "settings.modules.on": "On", + "settings.modules.off": "Off", + "settings.modules.installing": "Installation...", + "settings.modules.installing_warn": "Please <b>do not close Duniter</b> during this process!", + "settings.modules.uninstalling": "Removal...", + "graphs.tabs.blockchain": "Blockchain", + "graphs.tabs.currency": "Currency", + "graphs.blockchain.range": "Graphs for the last X blocks: (please choose X value)", + "graphs.blockchain.with.time": "Time variations graph", + "graphs.blockchain.with.speed": "Writing speed graph", + "graphs.blockchain.with.difficulty": "Difficulty graph", + "help.about_duniter": "A propos de Duniter", + "help.about_duniter.title": "About", + "help.about_duniter.subtitle": "Duniter Desktop", + "help.about_duniter.version": "Version: ", + "help.about_duniter.forum": "Forum", + "help.about_duniter.chat": "Chat", + "help.new_version_available": "Nouvelle version disponible", + "help.restart_required": "Redémarrer to apply changes", + "help.restart_required.message": "Please close Duniter and redémarrer it." +} diff --git a/app/js/lib/conf/translate.js b/app/js/lib/conf/translate.js index f0c8df55c45f35abe363db6a01273ab4ef127c4d..4b805e2a6ee970db0547b8ecac4178c4a7509fd4 100644 --- a/app/js/lib/conf/translate.js +++ b/app/js/lib/conf/translate.js @@ -3,9 +3,10 @@ module.exports = (app) => { app.config(['$translateProvider', ($translateProvider) => { $translateProvider.translations('en', require('./i18n/en')); + $translateProvider.translations('fr', require('./i18n/fr')); // Default language - $translateProvider.preferredLanguage('en'); + $translateProvider.preferredLanguage('fr'); // Other parameters $translateProvider.useSanitizeValueStrategy(''); diff --git a/app/views/main/home/tabs/overview.jade b/app/views/main/home/tabs/overview.jade index db0c00825c3d67eb62dd71b97c60a015d1db2255..1511eb9d357e2ec90babda5d86fd2a4521a19abe 100644 --- a/app/views/main/home/tabs/overview.jade +++ b/app/views/main/home/tabs/overview.jade @@ -68,7 +68,7 @@ .card-content i.fa.fa-chain.fa-5x .card-title - span {{ current_number }} + span {{ current_number | number:0}} .card-action p {{ 'home.current.number' | translate }} @@ -77,7 +77,7 @@ .card-content i.fa.fa-users.fa-5x .card-title - span {{ current_membersCount }} + span {{ current_membersCount | number:0 }} .card-action p {{ 'home.current.membersCount' | translate }} @@ -96,7 +96,7 @@ .card-content i.fa.fa-graduation-cap.fa-5x .card-title - span {{ current_powMin }} + span {{ current_powMin | number:0}} .card-action p {{ 'home.current.powMin' | translate }} @@ -105,7 +105,8 @@ .card-content i.fa.fa-money.fa-5x .card-title - span {{ monetaryMass }} UD + span {{ (monetaryMass / 1000 ) | number:0:'fr-FR' }} + span(title="{{'home.current.mmass_kud' | translate }}") kUD .card-action p {{ 'home.current.mmass' | translate }} diff --git a/index.js b/index.js index faed8caf259a612c7d3aac21599d74050a2f400d..d9a9e8b52a1cc7e4c0896588511c01cdead45eac 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,12 @@ -"use strict"; +'use strict'; -const _ = require('underscore') +const _ = require('underscore'); const co = require('co'); const fs = require('fs'); const bodyParser = require('body-parser'); -const http = require('http'); +const http = require('http'); const express = require('express'); -const path = require('path'); +const path = require('path'); const cors = require('cors'); const fileUpload = require('express-fileupload'); const webminController = require('./server/controller/webmin.js'); @@ -23,34 +23,34 @@ module.exports = { // Webmin options { value: '--webmhost <host>', desc: 'Local network interface to connect to (IP)' }, - { value: '--webmport <port>', desc: 'Local network port to connect', parser: parseInt } + { value: '--webmport <port>', desc: 'Local network port to connect', parser: parseInt }, ], cli: [{ - name: 'webstart', - desc: 'Starts Duniter as a daemon (background task).', - logs: false, - onConfiguredExecute: (server, conf, program, params) => co(function*() { - yield server.checkConfig() - const daemon = server.getDaemon('direct_webstart', 'webstart') - yield startDaemon(program, daemon) - }) + name : 'webstart', + desc : 'Starts Duniter as a daemon (background task).', + logs : false, + onConfiguredExecute: (server, conf, program, params) => co(function* () { + yield server.checkConfig(); + const daemon = server.getDaemon('direct_webstart', 'webstart'); + yield startDaemon(program, daemon); + }), }, { - name: 'webrestart', - desc: 'Stops Duniter daemon and restart it with its web interface.', - logs: false, - onConfiguredExecute: (server, conf, program, params) => co(function*() { - yield server.checkConfig() - const daemon = server.getDaemon('direct_webstart', 'webrestart') - yield stopDaemon(daemon) - yield startDaemon(program, daemon) - }) + name : 'webrestart', + desc : 'Stops Duniter daemon and restart it with its web interface.', + logs : false, + onConfiguredExecute: (server, conf, program, params) => co(function* () { + yield server.checkConfig(); + const daemon = server.getDaemon('direct_webstart', 'webrestart'); + yield stopDaemon(daemon); + yield startDaemon(program, daemon); + }), }, { - name: 'direct_webstart', - desc: 'Do a webstart', - onDatabaseExecute: (server, conf, program, params, startServices, stopServices, stack) => co(function*(){ + name : 'direct_webstart', + desc : 'Do a webstart', + onDatabaseExecute: (server, conf, program, params, startServices, stopServices, stack) => co(function* () { try { @@ -73,35 +73,36 @@ module.exports = { app.use(fileUpload()); app.use(bodyParser.urlencoded({ - extended: true + extended: true, })); app.use(bodyParser.json()); const wbmin = webminController(server, startServices, stopServices, listDuniterPlugins, stack); const httpServer = http.createServer(app); httpServer.listen(PORT, HOTE); - server.logger.info("Web administration accessible at following address: http://%s:%s", HOTE, PORT); + server.logger.info('Web administration accessible at following address: http://%s:%s', HOTE, PORT); require('./server/lib/routes').webmin(wbmin, app); require('./server/lib/routes').webminWS(wbmin)(httpServer); - const uiDeps = listDuniterUIPlugins() + const uiDeps = listDuniterUIPlugins(); for (const dep of uiDeps) { // Eventual HTTP routing if (dep.required.duniterUI.route) { - const subApp = express() - dep.required.duniterUI.route(subApp, server, conf, program, params) - app.use('/modules/', subApp) + const subApp = express(); + dep.required.duniterUI.route(subApp, server, conf, program, params); + app.use('/modules/', subApp); } } - const currentBlock = yield server.dal.getCurrentBlockOrNull() + const currentBlock = yield server.dal.getCurrentBlockOrNull(); if (currentBlock) { - yield wbmin.startAllServices() + yield wbmin.startAllServices(); } // Never ending promise - return new Promise((resolve) => {}); + return new Promise((resolve) => { + }); /****************************************/ @@ -109,30 +110,30 @@ module.exports = { console.error(e); process.exit(1); } - }) - }] - } + }), + }], + }, }; function startDaemon(program, daemon) { - return co(function*() { + return co(function* () { - const PORT = program.webmport || 9220 + const PORT = program.webmport || 9221; const isPortAlreadyTaken = yield new Promise((resolve) => { - isPortTaken(PORT, (err, taken) => err ? reject(err) : resolve(taken)) - }) + isPortTaken(PORT, (err, taken) => err ? reject(err) : resolve(taken)); + }); if (isPortAlreadyTaken) { - console.error('Port ' + PORT + ' already used.') - process.exit(3) + console.error('Port ' + PORT + ' already used.'); + process.exit(3); } return new Promise((resolve, reject) => daemon.start((err) => { - if (err) return reject(err) - resolve() - })) - }) + if (err) return reject(err); + resolve(); + })); + }); } /** @@ -143,67 +144,70 @@ function startDaemon(program, daemon) { * @param fn */ function isPortTaken(port, fn) { - const net = require('net') + const net = require('net'); const tester = net.createServer() .once('error', function (err) { - if (err.code != 'EADDRINUSE') return fn(err) - fn(null, true) + if (err.code != 'EADDRINUSE') return fn(err); + fn(null, true); }) - .once('listening', function() { - tester.once('close', function() { fn(null, false) }) - .close() + .once('listening', function () { + tester.once('close', function () { + fn(null, false); + }) + .close(); }) - .listen(port) + .listen(port); } function stopDaemon(daemon) { return new Promise((resolve, reject) => daemon.stop((err) => { err && console.error(err); - if (err) return reject(err) - resolve() - })) + if (err) return reject(err); + resolve(); + })); } function listDuniterPlugins() { - return listPlugins(r => !!r.duniter || !!r.duniterUI) + return listPlugins(r => !!r.duniter || !!r.duniterUI); } function listDuniterUIPlugins() { - return listPlugins(r => !!r.duniterUI) + return listPlugins(r => !!r.duniterUI); } function listPlugins(conditionTest) { - const uiDependencies = [] - const pathToPackageJSON = path.resolve('./package.json') - const pkgJSON = JSON.parse(fs.readFileSync(pathToPackageJSON, 'utf8')) - const peerDeps = pkgJSON.peerDependencies || {} - const allDeps = _.extend(pkgJSON.dependencies || {}, pkgJSON.devDependencies || {}) - const deps = Object.keys(allDeps) + const uiDependencies = []; + const pathToPackageJSON = path.resolve('./package.json'); + const pkgJSON = JSON.parse(fs.readFileSync(pathToPackageJSON, 'utf8')); + const peerDeps = pkgJSON.peerDependencies || {}; + const allDeps = _.extend(pkgJSON.dependencies || {}, pkgJSON.devDependencies || {}); + const deps = Object.keys(allDeps); for (const dep of deps) { try { - const required = require(dep) + const required = require(dep); if (required && conditionTest(required)) { uiDependencies.push({ - name: dep, + name : dep, version: allDeps[dep], - locked: !!peerDeps[dep], - required - }) + locked : !!peerDeps[dep], + required, + }); } - } catch (e) {} + } catch (e) { + } } // Special: self dependency (if local package is also a module) if (pkgJSON.main && pkgJSON.main.match(/\.js/)) { // With NW.js, the main is an index.html file, which causes a bug - const dep = pkgJSON.name - const required = require(path.resolve('./' + pkgJSON.main)) + const dep = pkgJSON.name; + const required = require(path.resolve('./' + pkgJSON.main)); if (required && conditionTest(required)) { uiDependencies.push({ - name: dep, + name : dep, version: 'local', - locked: true, - required - }) + locked : true, + required, + }); } } - return uiDependencies + return uiDependencies; } diff --git a/package.json b/package.json index 9407d2675d7f1f4cb8a8951bac0e051ad7184681..1a6e6cd54bbb4e6a063318bbc01da0a06e58c780 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "build": "bower install && brunch build", "b": "brunch build", "watch": "brunch watch", - "start": "cd cesium && npm start", + "start": "brunch watch --server", + "cesium": "cd cesium && npm start", + "webstart": "node run.js direct_webstart", "test": "mocha --growl tests/" }, "repository": { @@ -54,7 +56,7 @@ "brunch": "2.10.9", "core-util-is": "1.0.2", "css-brunch": "2.0.0", - "duniter": "1.7.x", + "duniter": "^1.7.21", "fb-flo-brunch": "1.7.22", "jade-brunch": "2.0.0", "javascript-brunch": "2.0.0", diff --git a/yarn.lock b/yarn.lock index 8aff82f57e2c31e61ff1421ef6e60ef1b21e8f81..9959267c5ed522a3f22a10672e193a5690e5277e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2115,9 +2115,10 @@ domain-browser@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" -duniter@1.7.x: +duniter@^1.7.21: version "1.7.21" resolved "https://registry.yarnpkg.com/duniter/-/duniter-1.7.21.tgz#492f1a9ab6dccf22632d5cd7cd11af9a30cccfe4" + integrity sha512-4NyVGbb/ScHU96YN1f35IfT0rI0c7Ixr+fqXdAzEhr1AUJ3At5ZGroGhg5ZAGWYDXc/GRDk8nQtMbibcv8T10g== dependencies: "@types/leveldown" "^4.0.0" "@types/levelup" "^3.1.0"