summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics
diff options
context:
space:
mode:
authorJannik Schönartz2017-12-28 15:55:49 +0100
committerJannik Schönartz2017-12-28 15:55:49 +0100
commit086c7458fe2c59dbb907755648362917c615404e (patch)
treea0ddf550223e628e70bcf9fe33096c1f000d2742 /modules-available/statistics
parent[usb-lock-off] Switched to the _hw db structure. Adding a device and db contr... (diff)
parent[sysconfig] Restore long lost ajax functionality (diff)
downloadslx-admin-086c7458fe2c59dbb907755648362917c615404e.tar.gz
slx-admin-086c7458fe2c59dbb907755648362917c615404e.tar.xz
slx-admin-086c7458fe2c59dbb907755648362917c615404e.zip
Merge branch 'origin/master' into usb-lock-off
Diffstat (limited to 'modules-available/statistics')
-rw-r--r--modules-available/statistics/api.inc.php36
-rw-r--r--modules-available/statistics/inc/parser.inc.php3
-rw-r--r--modules-available/statistics/page.inc.php120
-rw-r--r--modules-available/statistics/pages/projectors.inc.php58
-rw-r--r--modules-available/statistics/templates/filterbox.html7
-rw-r--r--modules-available/statistics/templates/machine-main.html4
-rw-r--r--modules-available/statistics/templates/page-replace.html104
-rw-r--r--modules-available/statistics/templates/projector-list.html2
8 files changed, 237 insertions, 97 deletions
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index a614658a..a7a636b3 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -263,6 +263,7 @@ if ($type{0} === '~') {
// `devicetype`, `devicename`, `subid`, `machineuuid`
// Make sure all screens are in the general hardware table
$hwids = array();
+ $keepPair = array();
foreach ($screens as $port => $screen) {
if (!array_key_exists('name', $screen))
continue;
@@ -274,6 +275,7 @@ if ($type{0} === '~') {
$hwids[$screen['name']] = $hwid;
}
// Now add new entries
+ $keepPair[] = array($hwid, $port);
$machinehwid = Database::insertIgnore('machine_x_hw', 'machinehwid', array(
'hwid' => $hwid,
'machineuuid' => $uuid,
@@ -302,30 +304,30 @@ if ($type{0} === '~') {
Database::exec("DELETE FROM machine_x_hw_prop WHERE machinehwid = :machinehwid AND prop NOT LIKE '@%'",
array('machinehwid' => $machinehwid));
} else {
- $qs = '?' . str_repeat(',?', count($validProps) - 1);
- array_unshift($validProps, $machinehwid);
- Database::exec("DELETE FROM machine_x_hw_prop"
- . " WHERE machinehwid = ? AND prop NOT LIKE '@%' AND prop NOT IN ($qs)",
- $validProps);
+ Database::exec("DELETE FROM machine_x_hw_prop
+ WHERE machinehwid = :mhwid AND prop NOT LIKE '@%' AND prop NOT IN (:props)", array(
+ 'mhwid' => $machinehwid,
+ 'props' => array_values($validProps),
+ ));
}
}
// Remove/disable stale entries
- if (empty($hwids)) {
+ if (empty($keepPair)) {
// No screens connected at all, purge all screen entries for this machine
- Database::exec("UPDATE machine_x_hw x, statistic_hw h"
- . " SET x.disconnecttime = UNIX_TIMESTAMP()"
- . " WHERE x.machineuuid = :uuid AND x.hwid = h.hwid AND h.hwtype = :type AND x.disconnecttime = 0",
+ Database::exec("UPDATE machine_x_hw x, statistic_hw h
+ SET x.disconnecttime = UNIX_TIMESTAMP()
+ WHERE x.machineuuid = :uuid AND x.hwid = h.hwid AND h.hwtype = :type AND x.disconnecttime = 0",
array('uuid' => $uuid, 'type' => DeviceType::SCREEN));
} else {
// Some screens connected, make sure old entries get removed
- $params = array_values($hwids);
- array_unshift($params, $uuid);
- array_unshift($params, DeviceType::SCREEN);
- $qs = '?' . str_repeat(',?', count($hwids) - 1);
- Database::exec("UPDATE machine_x_hw x, statistic_hw h"
- . " SET x.disconnecttime = UNIX_TIMESTAMP()"
- . " WHERE h.hwid = x.hwid AND x.disconnecttime = 0 AND h.hwtype = ? AND x.machineuuid = ? AND x.hwid NOT IN ($qs)", $params);
-
+ Database::exec("UPDATE machine_x_hw x, statistic_hw h
+ SET x.disconnecttime = UNIX_TIMESTAMP()
+ WHERE (x.hwid, x.devpath) NOT IN (:pairs) AND x.disconnecttime = 0 AND h.hwtype = :type
+ AND x.machineuuid = :uuid", array(
+ 'pairs' => $keepPair,
+ 'uuid' => $uuid,
+ 'type' => DeviceType::SCREEN,
+ ));
}
}
} else if ($type === '~suspend') {
diff --git a/modules-available/statistics/inc/parser.inc.php b/modules-available/statistics/inc/parser.inc.php
index acf6ebd4..679055a7 100644
--- a/modules-available/statistics/inc/parser.inc.php
+++ b/modules-available/statistics/inc/parser.inc.php
@@ -99,8 +99,8 @@ class Parser {
$hdds = array();
// Could have more than one disk - linear scan
$lines = preg_split("/[\r\n]+/", $data);
- $dev = false;
$i = 0;
+ $mbrToMbFactor = $sectorToMbFactor = 0;
foreach ($lines as $line) {
if (preg_match('/^Disk (\S+):.* (\d+) bytes/i', $line, $out)) {
// --- Beginning of MBR disk ---
@@ -260,7 +260,6 @@ class Parser {
public static function parseSmartctl(&$hdds, $data)
{
$lines = preg_split("/[\r\n]+/", $data);
- $i = 0;
foreach ($lines as $line) {
if (preg_match('/^NEXTHDD=(.+)$/', $line, $out)) {
unset($dev);
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index c3ecf52b..ea5b6f03 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -21,6 +21,11 @@ class Page_Statistics extends Page
private $query;
+ /**
+ * @var bool whether we have a SubPage from the pages/ subdir
+ */
+ private $haveSubpage;
+
/* PHP sucks, no static, const array definitions... Or am I missing something? */
public function initConstants()
{
@@ -125,53 +130,6 @@ class Page_Statistics extends Page
/* TODO ... */
}
- /*
- * TODO: Move to separate unit... hardware configurator?
- */
-
- protected function handleProjector($action)
- {
- $hwid = Request::post('hwid', false, 'int');
- if ($hwid === false) {
- Util::traceError('Param hwid missing');
- }
- if ($action === 'addprojector') {
- Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
- . ' VALUES (:hwid, :prop, :value)', array(
- 'hwid' => $hwid,
- 'prop' => 'projector',
- 'value' => 'true',
- ));
- } else {
- Database::exec('DELETE FROM statistic_hw_prop WHERE hwid = :hwid AND prop = :prop', array(
- 'hwid' => $hwid,
- 'prop' => 'projector',
- ));
- }
- if (Module::isAvailable('sysconfig')) {
- ConfigTgz::rebuildAllConfigs();
- }
- Util::redirect('?do=statistics&show=projectors');
- }
-
- protected function showProjectors()
- {
- $res = Database::simpleQuery('SELECT h.hwname, h.hwid FROM statistic_hw h'
- . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)"
- . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array(
- 'projector' => 'projector',
- 'screen' => DeviceType::SCREEN,
- ));
- $data = array(
- 'projectors' => $res->fetchAll(PDO::FETCH_ASSOC)
- );
- Render::addTemplate('projector-list', $data);
- }
-
- /*
- * End TODO
- */
-
protected function doPreprocess()
{
$this->initConstants();
@@ -180,24 +138,42 @@ class Page_Statistics extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
- $action = Request::post('action');
- if ($action === 'setnotes') {
- $uuid = Request::post('uuid', '', 'string');
- $text = Request::post('content', '', 'string');
- if (empty($text)) {
- $text = null;
+
+ $show = Request::any('show', 'stat', 'string');
+ $show = preg_replace('/[^a-z0-9_\-]/', '', $show);
+
+ if (file_exists('modules/statistics/pages/' . $show . '.inc.php')) {
+
+ require_once 'modules/statistics/pages/' . $show . '.inc.php';
+ $this->haveSubpage = true;
+ SubPage::doPreprocess();
+
+ } else {
+
+ $action = Request::post('action');
+ if ($action === 'setnotes') {
+ $uuid = Request::post('uuid', '', 'string');
+ $text = Request::post('content', '', 'string');
+ if (empty($text)) {
+ $text = null;
+ }
+ Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
+ 'uuid' => $uuid,
+ 'text' => $text,
+ ));
+ Message::addSuccess('notes-saved');
+ Util::redirect('?do=Statistics&uuid=' . $uuid);
+ } elseif ($action === 'delmachines') {
+ $this->deleteMachines();
+ Util::redirect('?do=statistics', true);
}
- Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
- 'uuid' => $uuid,
- 'text' => $text,
- ));
- Message::addSuccess('notes-saved');
- Util::redirect('?do=Statistics&uuid=' . $uuid);
- } elseif ($action === 'addprojector' || $action === 'delprojector') {
- $this->handleProjector($action);
- } elseif ($action === 'delmachines') {
- $this->deleteMachines();
- Util::redirect('?do=statistics', true);
+
+ }
+
+ if (Request::isPost()) {
+ // Make sure we don't render any content for POST requests - should be handled above and then
+ // redirected properly
+ Util::redirect('?do=statistics');
}
}
@@ -229,6 +205,11 @@ class Page_Statistics extends Page
protected function doRender()
{
+ if ($this->haveSubpage) {
+ SubPage::doRender();
+ return;
+ }
+
$uuid = Request::get('uuid', false, 'string');
if ($uuid !== false) {
$this->showMachine($uuid);
@@ -236,10 +217,6 @@ class Page_Statistics extends Page
}
$show = Request::get('show', 'stat', 'string');
- if ($show === 'projectors') {
- $this->showProjectors();
- return;
- }
/* read filter */
$this->query = Request::any('filters', false);
@@ -622,7 +599,6 @@ class Page_Statistics extends Page
. ' badsectors ' . $xtra . ' FROM machine'
. " $join WHERE $where $sort", $args);
$rows = array();
- $NOW = time();
$singleMachine = 'none';
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if ($singleMachine === 'none') {
@@ -894,7 +870,7 @@ class Page_Statistics extends Page
continue; // Don't differentiate between session and idle for non-clients
if ($first && $row['dateline'] > $cutoff && $client['lastboot'] > $cutoff) {
// Special case: offline before
- $spans['graph'] .= '<div style="background:#444;left:0%;width:' . round((min($row['dateline'], $client['lastboot']) - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:' . round((min($row['dateline'], $client['lastboot']) - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
}
$first = false;
if ($row['dateline'] + $row['data'] < $cutoff || $row['data'] > 864000) {
@@ -931,10 +907,10 @@ class Page_Statistics extends Page
}
if ($first && $client['lastboot'] > $cutoff) {
// Special case: offline before
- $spans['graph'] .= '<div style="background:#444;left:0%;width:' . round(($client['lastboot'] - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:' . round(($client['lastboot'] - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
} elseif ($first) {
// Not seen in last two weeks
- $spans['graph'] .= '<div style="background:#444;left:0%;width:100%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:100%">&nbsp;</div>';
}
if (isset($client['state_occupied'])) {
$spans['graph'] .= '<div style="background:#e99;left:' . round(($client['logintime'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['logintime'] + 900) * $scale, 2) . '%">&nbsp;</div>';
diff --git a/modules-available/statistics/pages/projectors.inc.php b/modules-available/statistics/pages/projectors.inc.php
new file mode 100644
index 00000000..cde542c6
--- /dev/null
+++ b/modules-available/statistics/pages/projectors.inc.php
@@ -0,0 +1,58 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', false, 'string');
+ if ($action !== false) {
+ self::handleProjector($action);
+ }
+ }
+
+ private static function handleProjector($action)
+ {
+ $hwid = Request::post('hwid', false, 'int');
+ if ($hwid === false) {
+ Util::traceError('Param hwid missing');
+ }
+ if ($action === 'addprojector') {
+ Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
+ . ' VALUES (:hwid, :prop, :value)', array(
+ 'hwid' => $hwid,
+ 'prop' => 'projector',
+ 'value' => 'true',
+ ));
+ } else {
+ Database::exec('DELETE FROM statistic_hw_prop WHERE hwid = :hwid AND prop = :prop', array(
+ 'hwid' => $hwid,
+ 'prop' => 'projector',
+ ));
+ }
+ if (Module::isAvailable('sysconfig')) {
+ ConfigTgz::rebuildAllConfigs();
+ }
+ Util::redirect('?do=statistics&show=projectors');
+ }
+
+ public static function doRender()
+ {
+ self::showProjectors();
+ }
+
+ private static function showProjectors()
+ {
+ $res = Database::simpleQuery('SELECT h.hwname, h.hwid FROM statistic_hw h'
+ . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)"
+ . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array(
+ 'projector' => 'projector',
+ 'screen' => DeviceType::SCREEN,
+ ));
+ $data = array(
+ 'projectors' => $res->fetchAll(PDO::FETCH_ASSOC)
+ );
+ Render::addTemplate('projector-list', $data);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/statistics/templates/filterbox.html b/modules-available/statistics/templates/filterbox.html
index 31daabc6..32464031 100644
--- a/modules-available/statistics/templates/filterbox.html
+++ b/modules-available/statistics/templates/filterbox.html
@@ -105,6 +105,7 @@ var slxFilterNames = {
slxLocations = {{{locations}}};
var slxFilterDel = '{{delimiter}}';
+var $modal, $queryForm;
document.addEventListener("DOMContentLoaded", function () {
@@ -217,7 +218,7 @@ function popupFilter(field) {
function addFilterFromForm() {
var argument1 = $('#argumentInput').val();
var argument2 = $('#argumentSelect').val();
- var argument = argument1 == '' ? argument2 : argument1;
+ var argument = argument1 ? argument1 : argument2;
var col = $('#columnSelect').val();
var op = $('#operatorSelect').val();
@@ -246,8 +247,8 @@ function toggleSort(field) {
/* equal sign should always be first, the rest doesn't matter*/
function myOpSort(a,b) {
- if (a == '=') { return -1; }
- else if (a == b) {return 0}
+ if (a === '=') { return -1; }
+ else if (a === b) {return 0}
else { return 1;}
}
diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html
index 19deb8b3..d8f2c521 100644
--- a/modules-available/statistics/templates/machine-main.html
+++ b/modules-available/statistics/templates/machine-main.html
@@ -144,11 +144,11 @@
<tr>
<td class="text-nowrap">{{lang_screens}}</td>
<td>
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
</form>
- <form method="post" action="?do=statistics" id="addprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="addprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="addprojector">
</form>
diff --git a/modules-available/statistics/templates/page-replace.html b/modules-available/statistics/templates/page-replace.html
new file mode 100644
index 00000000..f87610a2
--- /dev/null
+++ b/modules-available/statistics/templates/page-replace.html
@@ -0,0 +1,104 @@
+<h1>{{lang_replaceMachinesHeading}}</h1>
+
+<style>
+ .reptable {
+ border-collapse: separate;
+ border-spacing: 2px;
+ }
+ .reptable td.a {
+ padding: 2px;
+ border:1px solid #ccc;
+ border-radius: 3px;
+ background: #eee;
+ vertical-align: top;
+ }
+ .reptable td.b {
+ font-size: 300%;
+ }
+</style>
+
+<form method="post" action="?do=statistics&amp;show=replace">
+ <input type="hidden" name="token" value="{{token}}">
+ <table class="reptable">
+ <thead>
+ <tr>
+ <th>{{lang_replaceOld}}</th>
+ <th></th>
+ <th>{{lang_replaceNew}}</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#pairs}}
+ <tr>
+ <td class="a">
+ <div><b>{{oldhost}}</b> {{oldip}}</div>
+ <div class="slx-bold">{{oldmodel}}</div>
+ <div class="small">{{oldmac}} – {{olduuid}}</div>
+ <div>{{lang_lastSeen}}: {{oldlastseen_s}}</div>
+ </td>
+ <td class="b">&rightarrow;</td>
+ <td class="a">
+ <div><b>{{newhost}}</b> {{newip}}</div>
+ <div class="slx-bold">{{newmodel}}</div>
+ <div class="small">{{newmac}} – {{newuuid}}</div>
+ <div>{{lang_firstSeen}}: {{newfirstseen_s}}</div>
+ </td>
+ <td>
+ <div class="checkbox checkbox-inline">
+ <input type="checkbox" name="replace[]" value="{{olduuid}}x{{newuuid}}">
+ <label></label>
+ </div>
+ </td>
+ </tr>
+ {{/pairs}}
+ </tbody>
+ </table>
+
+ <div class="text-right">
+ <button type="button" class="btn btn-danger" name="action" value="replace" data-toggle="modal" data-target="#confirm-dialog">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ (<span id="rep-count">0</span>)
+ </button>
+ </div>
+
+ <div class="modal fade" id="confirm-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="myModalLabel">{{lang_replace}}</h4>
+ </div>
+ <div class="modal-body">
+ {{lang_sureReplaceNoUndo}}
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="submit" name="action" value="replace" class="btn btn-danger">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</form>
+
+<script type="application/javascript"><!--
+ document.addEventListener('DOMContentLoaded', function () {
+ $('td.a').click(function () {
+ var $cb = $(this).parent().find('input:checkbox');
+ $cb.prop('checked', !$cb.is(':checked'));
+ cbChanged();
+ });
+ $('input:checkbox').change(function () {
+ cbChanged();
+ });
+ function cbChanged() {
+ var cnt = $('input:checkbox:checked').length;
+ $('#rep-count').text(cnt).parent().prop('disabled', cnt === 0);
+ }
+ cbChanged();
+ });
+//--></script> \ No newline at end of file
diff --git a/modules-available/statistics/templates/projector-list.html b/modules-available/statistics/templates/projector-list.html
index bc9ecdbd..c33aae09 100644
--- a/modules-available/statistics/templates/projector-list.html
+++ b/modules-available/statistics/templates/projector-list.html
@@ -1,7 +1,7 @@
<div class="panel panel-default">
<div class="panel-heading">{{lang_projectors}}</div>
<div class="panel-body">
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
<p>{{lang_thoseAreProjectors}}</p>