Browse Source

Add peer node sync status in GUI (fixes #46)

Jakob Borg 11 years ago
parent
commit
9f63feef30
3 changed files with 61 additions and 29 deletions
  1. 27 13
      gui/app.js
  2. 14 16
      gui/index.html
  3. 20 0
      model.go

+ 27 - 13
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) {
-        if ($scope.connections[nodeCfg.NodeID]) {
-            return 'Connected';
+        var conn = $scope.connections[nodeCfg.NodeID];
+        if (conn) {
+            if (conn.Completion === 100) {
+                return 'In Sync';
+            } else {
+                return 'Syncing (' + conn.Completion + '%)';
+            }
         }
 
         return 'Disconnected';
     };
 
     $scope.nodeIcon = function (nodeCfg) {
-        if ($scope.connections[nodeCfg.NodeID]) {
-            return 'ok';
+        var conn = $scope.connections[nodeCfg.NodeID];
+        if (conn) {
+            if (conn.Completion === 100) {
+                return 'ok';
+            } else {
+                return 'refresh';
+            }
         }
 
         return 'minus';
@@ -165,7 +167,11 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
     $scope.nodeClass = function (nodeCfg) {
         var conn = $scope.connections[nodeCfg.NodeID];
         if (conn) {
-            return 'success';
+            if (conn.Completion === 100) {
+                return 'success';
+            } else {
+                return 'primary';
+            }
         }
 
         return 'info';
@@ -179,6 +185,14 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
         return '(unknown address)';
     };
 
+    $scope.nodeCompletion = function (nodeCfg) {
+        var conn = $scope.connections[nodeCfg.NodeID];
+        if (conn) {
+            return conn.Completion + '%';
+        }
+        return '';
+    };
+
     $scope.nodeVer = function (nodeCfg) {
         if (nodeCfg.NodeID === $scope.myID) {
             return $scope.version;

+ 14 - 16
gui/index.html

@@ -67,31 +67,31 @@ thead tr th {
                     <tbody>
                     <!-- myself -->
                     <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="glyphicon glyphicon-ok"></span> This node
                             </span>
                         </td>
-                        <td style="width:12%">
+                        <td style="width:10%">
                             <span class="text-monospace">{{nodeName(nodeCfg)}}</span>
                         </td>
                         <td style="width:20%">{{version}}</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
                             <span class="text-muted glyphicon glyphicon-chevron-down"></span>
                         </td>
-                        <td style="width:10%" class="text-right">
+                        <td style="width:9%" class="text-right">
                             {{outbps | metric}}bps
                             <span class="text-muted glyphicon glyphicon-chevron-up"></span>
                         </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>
                         </td>
                     </tr>
                     <!-- all other nodes -->
                     <tr ng-repeat="nodeCfg in otherNodes()">
-                        <td class="text-center">
+                        <td>
                             <span class="label label-{{nodeClass(nodeCfg)}}">
                                 <span class="glyphicon glyphicon-{{nodeIcon(nodeCfg)}}"></span> {{nodeStatus(nodeCfg)}}
                             </span>
@@ -99,12 +99,8 @@ thead tr th {
                         <td>
                             <span class="text-monospace">{{nodeName(nodeCfg)}}</span>
                         </td>
-                        <td>
-                            {{nodeVer(nodeCfg)}}
-                        </td>
-                        <td>
-                            {{nodeAddr(nodeCfg)}}
-                        </td>
+                        <td>{{nodeVer(nodeCfg)}}</td>
+                        <td>{{nodeAddr(nodeCfg)}}</td>
                         <td class="text-right">
                             <abbr title="{{connections[nodeCfg.NodeID].InBytesTotal | binary}}B">{{connections[nodeCfg.NodeID].inbps | metric}}bps</abbr>
                             <span class="text-muted glyphicon glyphicon-chevron-down"></span>
@@ -167,10 +163,12 @@ thead tr th {
     <div class="row">
         <div class="col-md-6">
             <div class="panel panel-info">
-                <div class="panel-heading"><h3 class="panel-title">System</h3></div>
-                <div class="panel-body">
-                    <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>
+                <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">
+                        <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>
+                    </div>
                 </div>
             </div>
         </div>

+ 20 - 0
model.go

@@ -158,6 +158,7 @@ type ConnectionInfo struct {
 	Address       string
 	ClientID      string
 	ClientVersion string
+	Completion    int
 }
 
 // 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
 	}
 
+	m.gmut.RLock()
 	m.pmut.RLock()
+	m.rmut.RLock()
+
+	var tot int
+	for _, f := range m.global {
+		tot += f.Size()
+	}
 
 	var res = make(map[string]ConnectionInfo)
 	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 {
 			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
 	}
 
+	m.rmut.RUnlock()
 	m.pmut.RUnlock()
+	m.gmut.RUnlock()
 	return res
 }