mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +00:00
Add peer node sync status in GUI (fixes #46)
This commit is contained in:
parent
c171780c0d
commit
9f63feef30
36
gui/app.js
36
gui/app.js
@ -138,25 +138,27 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.nodeIcon = function (nodeCfg) {
|
|
||||||
if ($scope.connections[nodeCfg.NodeID]) {
|
|
||||||
return 'ok';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'minus';
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.nodeStatus = function (nodeCfg) {
|
$scope.nodeStatus = function (nodeCfg) {
|
||||||
if ($scope.connections[nodeCfg.NodeID]) {
|
var conn = $scope.connections[nodeCfg.NodeID];
|
||||||
return 'Connected';
|
if (conn) {
|
||||||
|
if (conn.Completion === 100) {
|
||||||
|
return 'In Sync';
|
||||||
|
} else {
|
||||||
|
return 'Syncing (' + conn.Completion + '%)';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Disconnected';
|
return 'Disconnected';
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.nodeIcon = function (nodeCfg) {
|
$scope.nodeIcon = function (nodeCfg) {
|
||||||
if ($scope.connections[nodeCfg.NodeID]) {
|
var conn = $scope.connections[nodeCfg.NodeID];
|
||||||
|
if (conn) {
|
||||||
|
if (conn.Completion === 100) {
|
||||||
return 'ok';
|
return 'ok';
|
||||||
|
} else {
|
||||||
|
return 'refresh';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'minus';
|
return 'minus';
|
||||||
@ -165,7 +167,11 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
$scope.nodeClass = function (nodeCfg) {
|
$scope.nodeClass = function (nodeCfg) {
|
||||||
var conn = $scope.connections[nodeCfg.NodeID];
|
var conn = $scope.connections[nodeCfg.NodeID];
|
||||||
if (conn) {
|
if (conn) {
|
||||||
|
if (conn.Completion === 100) {
|
||||||
return 'success';
|
return 'success';
|
||||||
|
} else {
|
||||||
|
return 'primary';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'info';
|
return 'info';
|
||||||
@ -179,6 +185,14 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
|||||||
return '(unknown address)';
|
return '(unknown address)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.nodeCompletion = function (nodeCfg) {
|
||||||
|
var conn = $scope.connections[nodeCfg.NodeID];
|
||||||
|
if (conn) {
|
||||||
|
return conn.Completion + '%';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
$scope.nodeVer = function (nodeCfg) {
|
$scope.nodeVer = function (nodeCfg) {
|
||||||
if (nodeCfg.NodeID === $scope.myID) {
|
if (nodeCfg.NodeID === $scope.myID) {
|
||||||
return $scope.version;
|
return $scope.version;
|
||||||
|
@ -67,31 +67,31 @@ thead tr th {
|
|||||||
<tbody>
|
<tbody>
|
||||||
<!-- myself -->
|
<!-- myself -->
|
||||||
<tr class="text-muted" ng-repeat="nodeCfg in thisNode()">
|
<tr class="text-muted" ng-repeat="nodeCfg in thisNode()">
|
||||||
<td style="width:13%" class="text-center">
|
<td style="width:12%">
|
||||||
<span class="label label-default">
|
<span class="label label-default">
|
||||||
<span class="glyphicon glyphicon-ok"></span> This node
|
<span class="glyphicon glyphicon-ok"></span> This node
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:12%">
|
<td style="width:10%">
|
||||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:20%">{{version}}</td>
|
<td style="width:20%">{{version}}</td>
|
||||||
<td style="width:25%">(this node)</td>
|
<td style="width:25%">(this node)</td>
|
||||||
<td style="width:10%" class="text-right">
|
<td style="width:9%" class="text-right">
|
||||||
{{inbps | metric}}bps
|
{{inbps | metric}}bps
|
||||||
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:10%" class="text-right">
|
<td style="width:9%" class="text-right">
|
||||||
{{outbps | metric}}bps
|
{{outbps | metric}}bps
|
||||||
<span class="text-muted glyphicon glyphicon-chevron-up"></span>
|
<span class="text-muted glyphicon glyphicon-chevron-up"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td style="width:7%" class="text-right">
|
||||||
<button type="button" ng-click="editNode(nodeCfg)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span> Edit</button>
|
<button type="button" ng-click="editNode(nodeCfg)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span> Edit</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- all other nodes -->
|
<!-- all other nodes -->
|
||||||
<tr ng-repeat="nodeCfg in otherNodes()">
|
<tr ng-repeat="nodeCfg in otherNodes()">
|
||||||
<td class="text-center">
|
<td>
|
||||||
<span class="label label-{{nodeClass(nodeCfg)}}">
|
<span class="label label-{{nodeClass(nodeCfg)}}">
|
||||||
<span class="glyphicon glyphicon-{{nodeIcon(nodeCfg)}}"></span> {{nodeStatus(nodeCfg)}}
|
<span class="glyphicon glyphicon-{{nodeIcon(nodeCfg)}}"></span> {{nodeStatus(nodeCfg)}}
|
||||||
</span>
|
</span>
|
||||||
@ -99,12 +99,8 @@ thead tr th {
|
|||||||
<td>
|
<td>
|
||||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>{{nodeVer(nodeCfg)}}</td>
|
||||||
{{nodeVer(nodeCfg)}}
|
<td>{{nodeAddr(nodeCfg)}}</td>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{nodeAddr(nodeCfg)}}
|
|
||||||
</td>
|
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<abbr title="{{connections[nodeCfg.NodeID].InBytesTotal | binary}}B">{{connections[nodeCfg.NodeID].inbps | metric}}bps</abbr>
|
<abbr title="{{connections[nodeCfg.NodeID].InBytesTotal | binary}}B">{{connections[nodeCfg.NodeID].inbps | metric}}bps</abbr>
|
||||||
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
||||||
@ -167,13 +163,15 @@ thead tr th {
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="panel panel-info">
|
<div class="panel panel-info">
|
||||||
<div class="panel-heading"><h3 class="panel-title">System</h3></div>
|
<div class="panel-heading"><h3 class="panel-title"><a href="" data-toggle="collapse" data-target="#system">System</a></h3></div>
|
||||||
|
<div id="system" class="panel-collapse collapse">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p>{{system.sys | binary}}B RAM allocated, {{system.alloc | binary}}B in use</p>
|
<p>{{system.sys | binary}}B RAM allocated, {{system.alloc | binary}}B in use</p>
|
||||||
<p>{{system.cpuPercent | alwaysNumber | natural:1}}% CPU, {{system.goroutines | alwaysNumber}} goroutines</p>
|
<p>{{system.cpuPercent | alwaysNumber | natural:1}}% CPU, {{system.goroutines | alwaysNumber}} goroutines</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="panel panel-info">
|
<div class="panel panel-info">
|
||||||
<div class="panel-heading"><h3 class="panel-title"><a href="" data-toggle="collapse" data-target="#settingsTable">Settings</a></h3></div>
|
<div class="panel-heading"><h3 class="panel-title"><a href="" data-toggle="collapse" data-target="#settingsTable">Settings</a></h3></div>
|
||||||
|
20
model.go
20
model.go
@ -158,6 +158,7 @@ type ConnectionInfo struct {
|
|||||||
Address string
|
Address string
|
||||||
ClientID string
|
ClientID string
|
||||||
ClientVersion string
|
ClientVersion string
|
||||||
|
Completion int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectionStats returns a map with connection statistics for each connected node.
|
// ConnectionStats returns a map with connection statistics for each connected node.
|
||||||
@ -166,7 +167,14 @@ func (m *Model) ConnectionStats() map[string]ConnectionInfo {
|
|||||||
RemoteAddr() net.Addr
|
RemoteAddr() net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.gmut.RLock()
|
||||||
m.pmut.RLock()
|
m.pmut.RLock()
|
||||||
|
m.rmut.RLock()
|
||||||
|
|
||||||
|
var tot int
|
||||||
|
for _, f := range m.global {
|
||||||
|
tot += f.Size()
|
||||||
|
}
|
||||||
|
|
||||||
var res = make(map[string]ConnectionInfo)
|
var res = make(map[string]ConnectionInfo)
|
||||||
for node, conn := range m.protoConn {
|
for node, conn := range m.protoConn {
|
||||||
@ -178,10 +186,22 @@ func (m *Model) ConnectionStats() map[string]ConnectionInfo {
|
|||||||
if nc, ok := m.rawConn[node].(remoteAddrer); ok {
|
if nc, ok := m.rawConn[node].(remoteAddrer); ok {
|
||||||
ci.Address = nc.RemoteAddr().String()
|
ci.Address = nc.RemoteAddr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var have int
|
||||||
|
for _, f := range m.remote[node] {
|
||||||
|
if f.Equals(m.global[f.Name]) {
|
||||||
|
have += f.Size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ci.Completion = 100 * have / tot
|
||||||
|
|
||||||
res[node] = ci
|
res[node] = ci
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.rmut.RUnlock()
|
||||||
m.pmut.RUnlock()
|
m.pmut.RUnlock()
|
||||||
|
m.gmut.RUnlock()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user