diff --git a/webui-src/app/config.js b/webui-src/app/config.js deleted file mode 100644 index 7cae3b2..0000000 --- a/webui-src/app/config.js +++ /dev/null @@ -1,173 +0,0 @@ -let m = require('mithril'); -let rs = require('rswebui'); - -function sidebar(links) { - return m('.sidebar', - Object.keys(links) - .map(function(panelName) { - return m('a.sidebar-link' + (Panel.active === panelName ? - '#selected-sidebar-link' : ''), { - onclick: function() { - Panel.active = panelName; - }, - }, - panelName); - }), - ); -}; - -class Panel { - static component() { - return [ - m(Panel.list[Panel.active]), - ]; - } - constructor(name, content) { - Panel.list[name] = this; - // Turning object itself to a component - Object.assign(this, content); - } -}; -Panel.active = ''; -Panel.list = {}; - -function tooltip(text) { - return m('.tooltip', [ - m('i.fas.fa-info-circle'), - m('.tooltiptext', text) - ]); -}; - -function setMaxRates() { - let download = document.getElementById('download-limit') - .value; - let upload = document.getElementById('upload-limit') - .value; - if(isNaN(download) || isNaN(upload)) { - // TODO display error on setting non-numeric value - return; - } - rs.rsJsonApiRequest('/rsConfig/SetMaxDataRates', { - downKb: Number(download), - upKb: Number(upload), - }, - //TODO display success animation(fontawesome) - () => {}, - ); -}; -new Panel('Network', { - oninit: function() { - rs.rsJsonApiRequest('/rsConfig/GetMaxDataRates', {}, function(data) { - document.getElementById('download-limit') - .value = data.inKb; - document.getElementById('upload-limit') - .value = data.outKb; - }); - }, - view: function() { - return m('.node-panel.fadein', [ - m('.widget.widget-half', [ - m('h3', 'Network Configuration'), - m('hr'), - m('.grid-2col', [ - m('p', tooltip( - 'The download limit covers the whole application. However, in some situations, such as when transfering many files at once, the estimated bandwidth becomes unreliable and the total value reported by Retroshare might exceed that limit.' - ), 'Download limit(KB/s):'), - m('input#download-limit[type=number][name=download]', { - onblur: setMaxRates, - }), - m('p', tooltip( - 'The upload limit covers the entire software. Too small an upload limit may eventually block low priority services(forums, channels). A minimum recommended value is 50KB/s.' - ), 'Upload limit(KB/s):'), - m('input#upload-limit[type=number][name=upload]', { - onblur: setMaxRates, - }), - ]), - ]), - ]); - }, -}); -Panel.active = 'Network'; - -nodeInfo = { - setData: function(data) { - Object.assign(nodeInfo, data.status); - }, -}; - -new Panel('Node', { - oninit: function() { - rs.rsJsonApiRequest('/rsConfig/getConfigNetStatus', {}, nodeInfo.setData); - }, - view: function() { - return m('.node-panel', [ - m('.widget.widget-half', [ - m('h3', 'Public Information'), - m('hr'), - m('ul', [ - m('li', 'Name: ' + nodeInfo['ownName']), - m('li', 'Location ID: ' + nodeInfo['ownId']), - m('li', 'Firewall: ' + nodeInfo['firewalled']), - m('li', 'Port Forwarding: ' + nodeInfo['forwardPort']), - m('li', 'DHT: ' + nodeInfo['DHTActive']), - m('li', 'uPnP: ' + nodeInfo['uPnPActive']), - ]), - ]), - ]); - }, -}); - -let servicesInfo = { - list: [], - setData: function(data) { - servicesInfo.list = data.info.mServiceList; - }, -}; - -new Panel('Services', { - oninit: function() { - rs.rsJsonApiRequest('/rsServiceControl/getOwnServices', {}, - servicesInfo.setData); - }, - view: function() { - return m('.node-panel', [ - m('.widget', [ - m('h3', 'My Services'), - m('hr'), - m('table', [ - m('tr', [ - m('th', 'Name'), - m('th', 'ID'), - m('th', 'Version'), - ]), - servicesInfo.list.map(function(service) { - return m('tr', { - key: service.key, - }, [ - m('td', service.value.mServiceName), - m('td', service.value.mServiceType), - m('td', service.value.mVersionMajor + '.' + - service.value.mVersionMinor), - ]); - }), - ]), - ]), - ]); - }, -}); - - -let component = { - view: function() { - return m('.tab-page.fadein', [ - sidebar(Panel.list), - Panel.component(), - ]); - }, -}; - -new rs.Tab('config', component); -module.exports = { - component, -}; - diff --git a/webui-src/app/config/config_files.js b/webui-src/app/config/config_files.js new file mode 100644 index 0000000..a5e8b04 --- /dev/null +++ b/webui-src/app/config/config_files.js @@ -0,0 +1,38 @@ +let m = require('mithril'); +let rs = require('rswebui'); + +let Files = { + oninit: function() {}, + view: function() { + return [ + m('.widget', [ + m('h3', 'Shared Directories'), + m('hr'), + m('input'), + ]), + m('.widget', [ + m('h3', 'Transfer options'), + m('hr'), + m('.grid-2col', [ + m('p', 'Default chunk strategy:'), + m('input'), + m('p', 'Safety disk space limit:'), + m('input'), + ]), + ]), + m('.widget.widget-halfwidth', [ + m('h3', 'Incoming Directory'), + m('hr'), + m('input'), + ]), + m('.widget.widget-halfwidth', [ + m('h3', 'Partials Directory'), + m('hr'), + m('input'), + ]), + ]; + }, +}; + +module.exports = Files; + diff --git a/webui-src/app/config/config_network.js b/webui-src/app/config/config_network.js new file mode 100644 index 0000000..341eb0b --- /dev/null +++ b/webui-src/app/config/config_network.js @@ -0,0 +1,64 @@ +let m = require('mithril'); +let rs = require('rswebui'); + +function tooltip(text) { + return m('.tooltip', [ + m('i.fas.fa-info-circle'), + m('.tooltiptext', text) + ]); +}; + +function setMaxRates() { + let download = document.getElementById('download-limit') + .value; + let upload = document.getElementById('upload-limit') + .value; + if(isNaN(download) || isNaN(upload)) { + // TODO display error on setting non-numeric value + return; + } + rs.rsJsonApiRequest('/rsConfig/SetMaxDataRates', { + downKb: Number(download), + upKb: Number(upload), + }, + //TODO display success animation(fontawesome) + () => {}, + ); +}; + +let Network = { + oninit: function() { + rs.rsJsonApiRequest('/rsConfig/GetMaxDataRates', {}, function( + data) { + document.getElementById('download-limit') + .value = data.inKb; + document.getElementById('upload-limit') + .value = data.outKb; + }); + }, + view: function() { + return [ + m('.widget.widget-half', [ + m('h3', 'Network Configuration'), + m('hr'), + m('.grid-2col', [ + m('p', tooltip( + 'The download limit covers the whole application. However, in some situations, such as when transfering many files at once, the estimated bandwidth becomes unreliable and the total value reported by Retroshare might exceed that limit.' + ), 'Download limit(KB/s):'), + m( + 'input#download-limit[type=number][name=download]', { + onblur: setMaxRates, + }), + m('p', tooltip( + 'The upload limit covers the entire software. Too small an upload limit may eventually block low priority services(forums, channels). A minimum recommended value is 50KB/s.' + ), 'Upload limit(KB/s):'), + m('input#upload-limit[type=number][name=upload]', { + onblur: setMaxRates, + }), + ]), + ]), + ]; + }, +}; + +module.exports = Network; diff --git a/webui-src/app/config/config_node.js b/webui-src/app/config/config_node.js new file mode 100644 index 0000000..63e024c --- /dev/null +++ b/webui-src/app/config/config_node.js @@ -0,0 +1,34 @@ +let m = require('mithril'); +let rs = require('rswebui'); + +nodeInfo = { + setData: function(data) { + Object.assign(nodeInfo, data.status); + }, +}; + +let Node = { + oninit: function() { + rs.rsJsonApiRequest('/rsConfig/getConfigNetStatus', {}, nodeInfo + .setData); + }, + view: function() { + return [ + m('.widget.widget-half', [ + m('h3', 'Public Information'), + m('hr'), + m('ul', [ + m('li', 'Name: ' + nodeInfo['ownName']), + m('li', 'Location ID: ' + nodeInfo['ownId']), + m('li', 'Firewall: ' + nodeInfo['firewalled']), + m('li', 'Port Forwarding: ' + nodeInfo[ + 'forwardPort']), + m('li', 'DHT: ' + nodeInfo['DHTActive']), + m('li', 'uPnP: ' + nodeInfo['uPnPActive']), + ]), + ]), + ]; + }, +}; + +module.exports = Node; diff --git a/webui-src/app/config/config_resolver.js b/webui-src/app/config/config_resolver.js new file mode 100644 index 0000000..cb2109e --- /dev/null +++ b/webui-src/app/config/config_resolver.js @@ -0,0 +1,44 @@ +let m = require('mithril'); +let rs = require('rswebui'); + + +const sidebar = () => { + let active = 0; + const tabs = Object.keys(sections); + return { + view: () => m('.sidebar', + tabs.map((panelName, index) => m('a', { + href: '/config/' + panelName, + oncreate: m.route.link, + class: index === active ? + 'selected-sidebar-link' : '', + onclick: function() { + active = index; + }, + }, + panelName)), + ), + }; +}; + +let sections = { + network: require('config_network'), + node: require('config_node'), + services: require('config_services'), + files: require('config_files'), +}; + +const Layout = { + view: vnode => m('.tab-page', [ + m(sidebar), + m('.node-panel', vnode.children), + ]) +}; + +module.exports = { + view: (vnode) => { + const tab = vnode.attrs.section; + return m(Layout, m(sections[tab])); + }, +}; + diff --git a/webui-src/app/config/config_services.js b/webui-src/app/config/config_services.js new file mode 100644 index 0000000..5f60ed0 --- /dev/null +++ b/webui-src/app/config/config_services.js @@ -0,0 +1,44 @@ +let m = require('mithril'); +let rs = require('rswebui'); + +let servicesInfo = { + list: [], + setData: function(data) { + servicesInfo.list = data.info.mServiceList; + }, +}; + +let Services = { + oninit: function() { + rs.rsJsonApiRequest('/rsServiceControl/getOwnServices', {}, + servicesInfo.setData); + }, + view: function() { + return [ + m('.widget', [ + m('h3', 'My Services'), + m('hr'), + m('table', [ + m('tr', [ + m('th', 'Name'), + m('th', 'ID'), + m('th', 'Version'), + ]), + servicesInfo.list.map(function(service) { + return m('tr', { + key: service.key, + }, [ + m('td', service.value.mServiceName), + m('td', service.value.mServiceType), + m('td', service.value.mVersionMajor + + '.' + + service.value.mVersionMinor), + ]); + }), + ]), + ]), + ]; + }, +}; + +module.exports = Services; diff --git a/webui-src/app/home.js b/webui-src/app/home.js index e6dd4aa..bc4fb05 100644 --- a/webui-src/app/home.js +++ b/webui-src/app/home.js @@ -1,9 +1,9 @@ 'use strict'; -var m = require('mithril'); -var rs = require('rswebui'); +let m = require('mithril'); +let rs = require('rswebui'); let CERT = ''; -let component = { +let Component = { oninit: getCert, view: function() { return m('.tab-page.fadein', [ @@ -35,8 +35,5 @@ function copyToClipboard() { document.execCommand('copy'); }; -new rs.Tab('home', component); -module.exports = { - component, -}; +module.exports = Component; diff --git a/webui-src/app/main.js b/webui-src/app/main.js index da1ff71..9df895e 100644 --- a/webui-src/app/main.js +++ b/webui-src/app/main.js @@ -2,48 +2,62 @@ let m = require('mithril'); let login = require('login'); let rs = require('rswebui'); -login.renderLoginPage(onSuccess); + +const navIcon = { + home: m('i.fas.fa-home'), + downloads: m('i.fas.fa-folder-open'), + config: m('i.fas.fa-cogs'), +}; + +const navbar = () => { + active = 0; + return { + view: (vnode) => m('nav.tab-menu', + Object.keys(vnode.attrs.links) + .map((linkName, i) => m('a.tab-menu-item', { + href: vnode.attrs.links[linkName], + class: active === i ? 'selected-tab-item' : '', + oncreate: m.route.link, + onclick: () => { + active = i + }, + }, [navIcon[linkName], linkName])), + ), + }; +}; + +const Layout = () => { + return { + view: (vnode) => m('.content', [ + m(navbar, { + links: { + home: '/home', + downloads: '/downloads', + config: '/config/network', + }, + }), + m('#tab-content', vnode.children), + ]), + }; +}; function onSuccess() { let home = require('home'); let dl = require('downloads'); - let config = require('config'); + let config = require('config_resolver'); - rs.Tab.active = 'home'; - m.route(document.getElementById('main'), '/home', rs.Tab.routeTable); - //renderMainStructure(); - //m.route(document.getElementById('tab-section'), '/home', { - // '/home': home.component, - // '/downloads': dl.component, - // '/config': config.component, - //}); + m.route(document.getElementById('main'), '/home', { + '/home': { + render: (v) => m(Layout, m(home)) + }, + '/downloads': { + render: (v) => m(Layout, m(dl)) + }, + '/config/:section': { + render: (v) => m(Layout, m(config, v.attrs)) + }, + }); }; -function renderMainStructure() { - m.render(document.getElementById('main'), [ - rs.Tab.menuBar(), - ]); -}; - -/* -function renderMainStructure() { - m.render(document.getElementById('main'), [ - rs.Tab.menuBar(), - m('nav.tab-container', - [ - m('a.tab-header[href=/home]', { - oncreate: m.route.link - }, 'Home'), - m('a.tab-header[href=/downloads]', { - oncreate: m.route.link - }, - 'Downloads'), - m('a.tab-header[href=/config]', { - oncreate: m.route.link - }, 'Config'), - ]), - m('div#tab-section') - ]); -}; -*/ +login.renderLoginPage(onSuccess); diff --git a/webui-src/make-src/build.sh b/webui-src/make-src/build.sh index 3853658..7a0fe99 100755 --- a/webui-src/make-src/build.sh +++ b/webui-src/make-src/build.sh @@ -23,12 +23,15 @@ if [ ! -d "$publicdest" ]; then mkdir $publicdest fi +# For using recursive directory search(requires bash v4+) +shopt -s globstar + if [ "$2" = "" ]||[ "$2" = "app.js" ]; then echo building app.js echo - copy template.js ... cp $src/make-src/template.js $publicdest/app.js - for filename in $src/app/*.js; do + for filename in $src/app/**/*.js; do fname=$(basename "$filename") fname="${fname%.*}" echo - adding $fname ...