commit 3d0a77036ce363e369aa360bb55c47cad2ccb2a5
Author: Stephen Beaver <sbeaver@netgate.com>
Date:   Thu Aug 18 09:15:21 2016 -0400

    Completed #6723\
    by making the OpenVPN widget update dynamically
    
    (cherry picked from commit f30e6bd49c773de28b5ec143add30fc900e7874d)

diff --git a/src/usr/local/www/widgets/widgets/openvpn.widget.php b/src/usr/local/www/widgets/widgets/openvpn.widget.php
index 86fee0ff62..554425c61f 100644
--- a/src/usr/local/www/widgets/widgets/openvpn.widget.php
+++ b/src/usr/local/www/widgets/widgets/openvpn.widget.php
@@ -71,9 +71,200 @@ if ($_GET['action']) {
 	}
 }
 
-$servers = openvpn_get_active_servers();
-$sk_servers = openvpn_get_active_servers("p2p");
-$clients = openvpn_get_active_clients();
+// Compose the table contents and pass it back to the ajax caller
+if ($_REQUEST && $_REQUEST['ajax']) {
+	printPanel();
+	exit;
+}
+
+// Output the widget panel from this function so that it can be called from the AJAX handler as well as
+// when first rendering the page
+function printPanel() {
+
+	$servers = openvpn_get_active_servers();
+	$sk_servers = openvpn_get_active_servers("p2p");
+	$clients = openvpn_get_active_clients();
+
+	$opstring = "";
+
+	foreach ($servers as $server):
+
+	$opstring .= "<div class=\"widget panel panel-default\">";
+	$opstring .=	"<div class=\"panel-heading\"><h2 class=\"panel-title\">" . htmlspecialchars($server['name']) . "</h2></div>";
+	$opstring .=	"<div class=\"table-responsive\">";
+	$opstring .=		"<table class=\"table table-striped table-hover table-condensed sortable-theme-bootstrap\" data-sortable>";
+	$opstring .=			"<thead>";
+	$opstring .=				"<tr>";
+	$opstring .=					"<th>" . gettext('Name/Time') . "</th>";
+	$opstring .=					"<th>" . gettext('Real/Virtual IP') . "</th>";
+	$opstring .=					"<th></th>";
+	$opstring .=				"</tr>";
+	$opstring .=			"</thead>";
+	$opstring .=			"<tbody>";
+
+				$rowIndex = 0;
+				foreach ($server['conns'] as $conn):
+					$evenRowClass = $rowIndex % 2 ? " listMReven" : " listMRodd";
+					$rowIndex++;
+
+	$opstring .=				"<tr name=\"" . "r:" . $server['mgmt'] . ":" . $conn['remote_host'] . "\" class=\"" . $evenRowClass . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$conn['common_name'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$conn['remote_host'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						"<i class=\"fa fa-times-circle\" ";
+	$opstring .=							"onclick=\"killClient('" . $server['mgmt'] . "', '" . $conn['remote_host'] . "');\" ";
+	$opstring .=							"style=\"cursor:pointer;\" ";
+	$opstring .=							"name=\"" . "i:" . $server['mgmt'] . ":" . $conn['remote_host'] . "\" ";
+	$opstring .=							"title=\"" . sprintf(gettext('Kill client connection from %s'), $conn['remote_host']) . "\">";
+	$opstring .=						"</i>";
+	$opstring .=					"</td>";
+	$opstring .=				"</tr>";
+	$opstring .=				"<tr name=\"" . "r:" . $server['mgmt'] . ":" . $conn['remote_host'] . "\" class=\"" . $evenRowClass . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$conn['connect_time'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$conn['virtual_addr'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td></td>";
+	$opstring .=				"</tr>";
+
+				endforeach;
+
+	$opstring .=			"</tbody>";
+	$opstring .=		"</table>";
+	$opstring .=	"</div>";
+	$opstring .= "</div>";
+
+	endforeach;
+
+	print($opstring);
+
+	if (!empty($sk_servers)):
+
+	$opstring = "";
+	$opstring .= "<div class=\"widget panel panel-default\">";
+	$opstring .=	"<div class=\"panel-heading\"><h2 class=\"panel-title\">" . gettext("Peer to Peer Server Instance Statistics") . "</h2></div>";
+	$opstring .=	"<div class=\"table-responsive\">";
+	$opstring .=		"<table class=\"table table-striped table-hover table-condensed sortable-theme-bootstrap\" data-sortable>";
+	$opstring .=			"<thead>";
+	$opstring .=				"<tr>";
+	$opstring .=					"<th>" . gettext('Nome/Time') . "</th>";
+	$opstring .=					"<th>" . gettext('Remote/Virtual IP') . "</th>";
+	$opstring .=					"<th></th>";
+	$opstring .=				"</tr>";
+	$opstring .=			"</thead>";
+	$opstring .=			"<tbody>";
+
+				foreach ($sk_servers as $sk_server):
+
+	$opstring .=				"<tr name=\"r:" . $sk_server['port'] . ":" . $sk_server['remote_host'] . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$sk_server['name'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$sk_server['remote_host'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+
+					if ($sk_server['status'] == "up") {
+						/* tunnel is up */
+	$opstring .=						"<i class=\"fa fa-arrow-up text-success\"></i>";
+					} else {
+						/* tunnel is down */
+	$opstring .=						"<i class=\"fa fa-arrow-down text-danger\"></i>";
+					}
+
+	$opstring .=					"</td>";
+	$opstring .=				"</tr>";
+	$opstring .=				"<tr name=\"r:" . $sk_server['port'] . ":" . $sk_server['remote_host'] . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$sk_server['connect_time'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$sk_server['virtual_addr'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td></td>";
+	$opstring .=				"</tr>";
+
+				endforeach;
+
+	$opstring .=			"</tbody>";
+	$opstring .=		"</table>";
+	$opstring .=	"</div>";
+	$opstring .= "</div>";
+
+	print($opstring);
+
+	endif;
+
+	if (!empty($clients)):
+		$opstring = "";
+
+	$opstring .= "<div class=\"widget panel panel-default\">";
+	$opstring .=	"<div class=\"panel-heading\"><h2 class=\"panel-title\">" . gettext("Client Instance Statistics") . "</h2></div>";
+	$opstring .=	"<div class=\"table-responsive\">";
+	$opstring .=		"<table class=\"table table-striped table-hover table-condensed sortable-theme-bootstrap\" data-sortable>";
+	$opstring .=			"<thead>";
+	$opstring .=				"<tr>";
+	$opstring .=					"<th>" . gettext('Name/Time') . "</th>";
+	$opstring .=					"<th>" . gettext('Remote/Virtual IP') . "</th>";
+	$opstring .=					"<th></th>";
+	$opstring .=				"</tr>";
+	$opstring .=			"</thead>";
+	$opstring .=			"<tbody>";
+
+				foreach ($clients as $client):
+
+	$opstring .=				"<tr name=\"r:" . client['port'] . ":" . $client['remote_host'] . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$client['name'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$client['remote_host'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+
+					if ($client['status'] == "up") {
+						/* tunnel is up */
+	$opstring .=						"<i class=\"fa fa-arrow-up text-success\"></i>";
+					} else {
+						/* tunnel is down */
+	$opstring .=						"<i class=\"fa fa-arrow-down text-danger\"></i>";
+					}
+
+	$opstring .=					"</td>";
+	$opstring .=				"</tr>";
+	$opstring .=				"<tr name=\"r:" . $client['port'] . ":" . $client['remote_host'] . "\">";
+	$opstring .=					"<td>";
+	$opstring .=						$client['connect_time'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td>";
+	$opstring .=						$client['virtual_addr'];
+	$opstring .=					"</td>";
+	$opstring .=					"<td></td>";
+	$opstring .=				"</tr>";
+
+				endforeach;
+
+	$opstring .=			"</tbody>";
+	$opstring .=		"</table>";
+	$opstring .=	"</div>";
+	$opstring .= "</div>";
+
+	print($opstring);
+
+	endif;
+
+	if ((empty($clients)) && (empty($servers)) && (empty($sk_servers))) {
+		print(gettext("No OpenVPN instances defined"));
+	}
+}
+
 ?>
 
 <script type="text/javascript">
@@ -98,179 +289,36 @@ $clients = openvpn_get_active_clients();
 			function(index,row) { $(row).fadeOut(1000); }
 		);
 	}
-//]]>
-</script>
-<div class="content">
-<?php foreach ($servers as $server): ?>
-
-<div class="widget panel panel-default">
-	<div class="panel-heading"><h2 class="panel-title"><?=htmlspecialchars($server['name']);?></h2></div>
-	<div class="table-responsive">
-		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
-			<thead>
-				<tr>
-					<th><?=gettext('Name/Time')?></th>
-					<th><?=gettext('Real/Virtual IP')?></th>
-					<th></th>
-				</tr>
-			</thead>
-			<tbody>
-<?php
-			$rowIndex = 0;
-			foreach ($server['conns'] as $conn):
-				$evenRowClass = $rowIndex % 2 ? " listMReven" : " listMRodd";
-				$rowIndex++;
-?>
-				<tr name="<?php echo "r:{$server['mgmt']}:{$conn['remote_host']}"; ?>" class="<?=$evenRowClass?>">
-					<td>
-						<?=$conn['common_name'];?>
-					</td>
-					<td>
-						<?=$conn['remote_host'];?>
-					</td>
-					<td>
-						<i class="fa fa-times-circle"
-							onclick="killClient('<?=$server['mgmt']; ?>', '<?=$conn['remote_host']; ?>');"
-							style="cursor:pointer;"
-							name="<?php echo "i:{$server['mgmt']}:{$conn['remote_host']}"; ?>"
-							title=<?=sprintf(gettext('Kill client connection from %s'), $conn['remote_host']);?>>
-						</i>
-					</td>
-				</tr>
-				<tr name="<?php echo "r:{$server['mgmt']}:{$conn['remote_host']}"; ?>" class="<?=$evenRowClass?>">
-					<td>
-						<?=$conn['connect_time'];?>
-					</td>
-					<td>
-						<?=$conn['virtual_addr'];?>
-					</td>
-					<td></td>
-				</tr>
-<?php
-			endforeach;
-?>
-			</tbody>
-		</table>
-	</div>
-</div>
 
-<?php
-endforeach;
+	// REfreh the panel
+	function get_update() {
+		var ajaxRequest;
 
-if (!empty($sk_servers)):
-?>
-<div class="widget panel panel-default">
-	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Peer to Peer Server Instance Statistics");?></h2></div>
-	<div class="table-responsive">
-		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
-			<thead>
-				<tr>
-					<th><?=gettext('Name/Time')?></th>
-					<th><?=gettext('Remote/Virtual IP')?></th>
-					<th></th>
-				</tr>
-			</thead>
-			<tbody>
-<?php
-			foreach ($sk_servers as $sk_server):
-?>
-				<tr name='<?php echo "r:{$sk_server['port']}:{$sk_server['remote_host']}"; ?>'>
-					<td>
-						<?=$sk_server['name'];?>
-					</td>
-					<td>
-						<?=$sk_server['remote_host'];?>
-					</td>
-					<td>
-<?php
-				if ($sk_server['status'] == "up") {
-					/* tunnel is up */
-					echo '<i class="fa fa-arrow-up text-success"></i>';
-				} else {
-					/* tunnel is down */
-					echo '<i class="fa fa-arrow-down text-danger"></i>';
-				}
-?>
-					</td>
-				</tr>
-				<tr name="<?php echo "r:{$sk_server['port']}:{$sk_server['remote_host']}"; ?>">
-					<td>
-						<?=$sk_server['connect_time'];?>
-					</td>
-					<td>
-						<?=$sk_server['virtual_addr'];?>
-					</td>
-					<td></td>
-				</tr>
-<?php
-			endforeach;
-?>
-			</tbody>
-		</table>
-	</div>
-</div>
+		ajaxRequest = $.ajax({
+				url: "/widgets/widgets/openvpn.widget.php",
+				type: "post",
+				data: { ajax: "ajax"}
+			});
 
-<?php
-endif;
+		// Deal with the results of the above ajax call
+		ajaxRequest.done(function (response, textStatus, jqXHR) {
+			$('#mainpanel').html(response);
 
-if (!empty($clients)):
-?>
-<div class="widget panel panel-default">
-	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Client Instance Statistics");?></h2></div>
-	<div class="table-responsive">
-		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
-			<thead>
-				<tr>
-					<th><?=gettext('Name/Time')?></th>
-					<th><?=gettext('Remote/Virtual IP')?></th>
-					<th></th>
-				</tr>
-			</thead>
-			<tbody>
-<?php
-			foreach ($clients as $client):
-?>
-				<tr name="<?php echo "r:{$client['port']}:{$client['remote_host']}"; ?>">
-					<td>
-						<?=$client['name'];?>
-					</td>
-					<td>
-					<?=$client['remote_host'];?>
-					</td>
-					<td>
-<?php
-				if ($client['status'] == "up") {
-					/* tunnel is up */
-					echo '<i class="fa fa-arrow-up text-success"></i>';
-				} else {
-					/* tunnel is down */
-					echo '<i class="fa fa-arrow-down text-danger"></i>';
-				}
-?>
-					</td>
-				</tr>
-				<tr name="<?php echo "r:{$client['port']}:{$client['remote_host']}"; ?>">
-					<td>
-						<?=$client['connect_time'];?>
-					</td>
-					<td>
-						<?=$client['virtual_addr'];?>
-					</td>
-					<td></td>
-				</tr>
-<?php
-			endforeach;
-?>
-			</tbody>
-		</table>
-	</div>
-</div>
+			// and do it again
+			setTimeout(get_update, 5000);
+		});
+	}
 
-<?php
-endif;
+	events.push(function(){
+		// Start polling for updates some small random number of seconds from now (so that all the widgets don't
+		// hit the server at exactly the same time)
+        setTimeout(get_update, Math.floor((Math.random() * 10000) + 1000));
+	});
+//]]>
+</script>
+<div id="mainpanel" class="content">
 
-if ((empty($clients)) && (empty($servers)) && (empty($sk_servers))) {
-	echo gettext("No OpenVPN instances defined");
-}
+<?php
+	printPanel();
 ?>
 </div>
