diff --git a/ui/Makefile b/ui/Makefile
index 48b4446d9..4be03228b 100644
--- a/ui/Makefile
+++ b/ui/Makefile
@@ -1,5 +1,6 @@
all:
mkdir -p build
jsx --target es3 -x jsx . ./build
+ rm -f ztui.min.js
minify build/*.js >>ztui.min.js
rm -rf build
diff --git a/ui/ZeroTierNetwork.jsx b/ui/ZeroTierNetwork.jsx
index 1dda11172..f842d7587 100644
--- a/ui/ZeroTierNetwork.jsx
+++ b/ui/ZeroTierNetwork.jsx
@@ -67,7 +67,7 @@ var ZeroTierNetwork = React.createClass({
-
+
);
}
diff --git a/ui/ZeroTierNode.jsx b/ui/ZeroTierNode.jsx
index 3782219ef..956b892c5 100644
--- a/ui/ZeroTierNode.jsx
+++ b/ui/ZeroTierNode.jsx
@@ -96,7 +96,7 @@ var ZeroTierNode = React.createClass({
},
handleNetworkIdEntry: function(event) {
this.networkInputElement = event.target;
- var nid = event.target.value;
+ var nid = this.networkInputElement.value;
if (nid) {
nid = nid.toLowerCase();
var nnid = '';
@@ -105,10 +105,10 @@ var ZeroTierNode = React.createClass({
nnid += nid.charAt(i);
}
this.networkToJoin = nnid;
- event.target.value = nnid;
+ this.networkInputElement.value = nnid;
} else {
this.networkToJoin = '';
- event.target.value = '';
+ this.networkInputElement.value = '';
}
},
@@ -138,9 +138,8 @@ var ZeroTierNode = React.createClass({
-
+
{
(this.tabIndex === 1) ? (
@@ -198,13 +197,13 @@ var ZeroTierNode = React.createClass({
)
}
-
+
{this.state.address} {this.state.online ? 'ONLINE' : 'OFFLINE'} {this.state.version}
-
+
diff --git a/ui/index.html b/ui/index.html
index 5ab32eb7b..857c7ddb9 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -1,16 +1,39 @@
-
-
-
-
- ZeroTier One
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ ZeroTier One
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/zerotier.css b/ui/zerotier.css
index 85ac9d6fb..2211ac59c 100644
--- a/ui/zerotier.css
+++ b/ui/zerotier.css
@@ -20,7 +20,6 @@ html,body {
.zeroTierNode {
width: 100%;
height: 100%;
- max-height: 100%;
padding: 0;
margin: 0;
display: table;
@@ -36,14 +35,6 @@ html,body {
padding: 0;
margin: 0;
}
-.zeroTierNode > .top > .logo {
- display: inline-block;
- padding: 0.1em 0 0 0;
- margin: 0;
- font-size: 12pt;
- font-weight: bold;
- float: right;
-}
.zeroTierNode > .top button {
display: inline-block;
padding: 0.25rem 0.75rem 0.25rem 0.75rem;
@@ -63,33 +54,39 @@ html,body {
}
.zeroTierNode > .middle {
- height: 100%;
width: 100%;
+ height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
display: table-row;
}
-.zeroTierNode > .middle > .middleScroll {
+.zeroTierNode > .middle > .middleCell {
+ width: 100%;
+ height: 100%;
+ display: table-cell;
+}
+.zeroTierNode > .middle > .middleCell > .middleScroll {
display: block;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
+ overflow: scroll;
overflow-x: hidden;
overflow-y: scroll;
background: #dddddd;
}
-.zeroTierNode > .middle > .middleScroll > .networks {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .networks {
display: block;
width: 100%;
- padding: 0;
+ padding: 0 0 0.25rem 0;
margin: 0;
border: 0;
text-align: left;
border-collapse: collapse;
}
-.zeroTierNode > .middle > .middleScroll > .networks > .network {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .networks > .network {
display: inline-block;
padding: 0.25rem;
margin: 0.25rem 0 0 1%;
@@ -98,36 +95,36 @@ html,body {
border: 1px solid #234447;
background: #ffffff;
}
-.zeroTierNode > .middle > .middleScroll > .peers {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers {
display: table;
width: 100%;
margin: 0;
border-collapse: collapse;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer {
width: 100%;
display: table-row;
background: #ffffff;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer:nth-child(odd) {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(odd) {
background: #f3f3f3;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer:nth-child(even) {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(even) {
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer .peerPathActive {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathActive {
font-size: 10pt;
color: #555555;
font-style: italic;
font-family: monospace;
white-space: nowrap;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer .peerPathPreferred {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathPreferred {
font-size: 10pt;
color: #000000;
font-family: monospace;
white-space: nowrap;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer .peerPathInactive {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathInactive {
font-size: 10pt;
font-family: monospace;
color: #aaaaaa;
@@ -135,18 +132,18 @@ html,body {
text-decoration: line-through;
white-space: nowrap;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peer > .f {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer > .f {
display: table-cell;
padding: 0.05rem 0.15rem 0.05rem 0.15rem;
font-size: 10pt;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peerHeader {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader {
width: 100%;
display: table-row;
background: #ffffff;
border-bottom: 1px solid #000000;
}
-.zeroTierNode > .middle > .middleScroll > .peers > .peerHeader > .f {
+.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader > .f {
display: table-cell;
font-size: 10pt;
padding: 0.05rem 0.15rem 0.05rem 0.15rem;
@@ -154,6 +151,7 @@ html,body {
}
.zeroTierNode > .bottom {
+ font-size: 12pt;
width: 100%;
overflow: hidden;
display: table-row;
@@ -165,17 +163,24 @@ html,body {
white-space: nowrap;
float: left;
padding: 0 0 0 0.5rem;
+ font-size: 12pt;
+ height: 100%;
}
.zeroTierNode > .bottom > .left > .statusLine {
font-family: monospace;
white-space: nowrap;
font-size: 12pt;
+ height: 100%;
}
.zeroTierNode > .bottom > .right {
- background: #91a2a3;
text-align: right;
+ height: 100%;
white-space: nowrap;
float: right;
+ font-size: 12pt;
+}
+.zeroTierNode > .bottom > .right form {
+ height: 100%;
}
.zeroTierNode > .bottom > .right input {
font-family: monospace;
@@ -183,10 +188,13 @@ html,body {
background: #ffffff;
color: #000000;
outline: none;
- border: 1px solid #234447;
+ outline-style: none;
+ box-shadow: 0;
+ border: 0;
margin: 0;
- padding: 0.05rem 0.25rem 0.05rem 0.25rem;
- display: inline-block;
+ padding: 0 0.25rem 0 0.25rem;
+ display: inline;
+ height: 100%;
}
.zeroTierNode > .bottom > .right button {
display: inline-block;
@@ -196,10 +204,14 @@ html,body {
color: #000000;
margin: 0;
padding: 0.05rem 0.75rem 0.05rem 0.75rem;
+ outline: none;
+ outline-style: none;
height: 100%;
}
.zeroTierNode > .bottom > .right button:hover {
cursor: pointer;
+ outline: none;
+ outline-style: none;
border: 1px solid #000000;
}
@@ -217,7 +229,7 @@ html,body {
font-size: 12pt;
}
.zeroTierNetwork .networkInfo .networkId {
- font-size: 10pt;
+ font-size: 11pt;
font-family: monospace;
color: #91a2a3;
}
diff --git a/ui/ztui.min.js b/ui/ztui.min.js
index f4213a0f8..cefd9e877 100644
--- a/ui/ztui.min.js
+++ b/ui/ztui.min.js
@@ -1,3 +1 @@
-var ZeroTierNetwork=React.createClass({displayName:"ZeroTierNetwork",getInitialState:function(){return{}},leaveNetwork:function(e){Ajax.call({url:"network/"+this.props.nwid+"?auth="+this.props.authToken,cache:!1,type:"DELETE",success:function(e){this.props.onNetworkDeleted&&this.props.onNetworkDeleted(this.props.nwid)}.bind(this),error:function(e){}.bind(this)}),e.preventDefault()},render:function(){return React.createElement("div",{className:"zeroTierNetwork"},React.createElement("div",{className:"networkInfo"},React.createElement("span",{className:"networkId"},this.props.nwid)," ",React.createElement("span",{className:"networkName"},this.props.name)),React.createElement("div",{className:"networkProps"},React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Status"),React.createElement("div",{className:"value"},this.props.status)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Type"),React.createElement("div",{className:"value"},this.props.type)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MAC"),React.createElement("div",{className:"value zeroTierAddress"},this.props.mac)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MTU"),React.createElement("div",{className:"value"},this.props.mtu)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Broadcast"),React.createElement("div",{className:"value"},this.props.broadcastEnabled?"ENABLED":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Bridging"),React.createElement("div",{className:"value"},this.props.bridge?"ACTIVE":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Device"),React.createElement("div",{className:"value"},this.props.portDeviceName?this.props.portDeviceName:"(none)")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Managed IPs"),React.createElement("div",{className:"value ipList"},this.props.assignedAddresses.map(function(e){return React.createElement("div",{key:e,className:"ipAddress"},e)})))),React.createElement("button",{className:"leaveNetworkButton",onClick:this.leaveNetwork},"Leave Network"))}}); var ZeroTierNode=React.createClass({displayName:"ZeroTierNode",getInitialState:function(){return{address:"----------",online:!1,version:"_._._",_networks:[],_peers:[]}},ago:function(e){if(e>0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=e.target.value;if(t){t=t.toLowerCase();for(var a="",s=0;ss;++s)"0123456789abcdef".indexOf(t.charAt(s))>=0&&(a+=t.charAt(s));this.networkToJoin=a,e.target.value=a}else this.networkToJoin="",e.target.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=e.target.value;if(t){t=t.toLowerCase();for(var a="",s=0;ss;++s)"0123456789abcdef".indexOf(t.charAt(s))>=0&&(a+=t.charAt(s));this.networkToJoin=a,e.target.value=a}else this.networkToJoin="",e.target.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=e.target.value;if(t){t=t.toLowerCase();for(var a="",s=0;ss;++s)"0123456789abcdef".indexOf(t.charAt(s))>=0&&(a+=t.charAt(s));this.networkToJoin=a,e.target.value=a}else this.networkToJoin="",e.target.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var a="",n=0;nn;++n)"0123456789abcdef".indexOf(t.charAt(n))>=0&&(a+=t.charAt(n));this.networkToJoin=a,this.networkInputElement.value=a}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a