summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc
diff options
context:
space:
mode:
authorSimon Rettberg2020-04-20 11:49:17 +0200
committerSimon Rettberg2020-04-20 11:49:17 +0200
commit5eaa4292c6db2c1ee1282c938c899dc5b88db65f (patch)
tree137eaa063302b055ddec03e2c4c3ff5c084f11bf /modules-available/statistics/inc
parent[serversetup-bwlp-ipxe] Fix: Imported PXELINUX entries are invalid (diff)
downloadslx-admin-5eaa4292c6db2c1ee1282c938c899dc5b88db65f.tar.gz
slx-admin-5eaa4292c6db2c1ee1282c938c899dc5b88db65f.tar.xz
slx-admin-5eaa4292c6db2c1ee1282c938c899dc5b88db65f.zip
[statistics] New filter UI
Diffstat (limited to 'modules-available/statistics/inc')
-rw-r--r--modules-available/statistics/inc/statisticsfilter.inc.php270
1 files changed, 151 insertions, 119 deletions
diff --git a/modules-available/statistics/inc/statisticsfilter.inc.php b/modules-available/statistics/inc/statisticsfilter.inc.php
index 1bc512f5..6999654d 100644
--- a/modules-available/statistics/inc/statisticsfilter.inc.php
+++ b/modules-available/statistics/inc/statisticsfilter.inc.php
@@ -6,9 +6,9 @@
class StatisticsFilter
{
/**
- * Delimiter for js_selectize filters
+ * Legacy delimiter for js_selectize filters - used to redirect old URLs
*/
- const DELIMITER = '~,~';
+ const LEGACY_DELIMITER = '~,~';
const SIZE_ID44 = array(0, 8, 16, 24, 30, 40, 50, 60, 80, 100, 120, 150, 180, 250, 300, 400, 500, 1000, 2000, 4000);
const SIZE_RAM = array(1, 2, 3, 4, 6, 8, 10, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 320, 480, 512, 768, 1024);
@@ -90,61 +90,34 @@ class StatisticsFilter
}
/* parse a query into an array of filters */
- public static function parseQuery($query)
+ public static function parseQuery()
{
- $operators = ['<=', '>=', '!=', '!~', '=', '~', '<', '>'];
+ // Get current settings from GET
+ $currentValues = self::loadFilterFromGet();
$filters = [];
- if (empty($query))
- return $filters;
- foreach (explode(self::DELIMITER, $query) as $q) {
- $q = trim($q);
- if (empty($q))
+ foreach ($currentValues as $filterType => $data) {
+ if (!$data['filter'])
continue;
- // Special case: User pasted UUID, turn into filter
- if (preg_match('/^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/', $q)) {
- $filters[] = new StatisticsFilter('machineuuid', '=', $q);
- continue;
- }
- // Special case: User pasted IP, turn into filter
- if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $q)) {
- $filters[] = new StatisticsFilter('clientip', '=', $q);
- continue;
- }
- /* find position of first operator */
- $pos = 10000;
- $operator = false;
- foreach ($operators as $op) {
- $newpos = strpos($q, $op);
- if ($newpos > -1 && ($newpos < $pos)) {
- $pos = $newpos;
- $operator = $op;
- }
- }
- if ($pos == 10000) {
- error_log("couldn't find operator in segment " . $q);
- /* TODO */
- continue;
- }
- $lhs = trim(substr($q, 0, $pos));
- $rhs = trim(substr($q, $pos + strlen($operator)));
-
- if ($lhs === 'gbram') {
- $filters[] = new RamGbStatisticsFilter($operator, $rhs);
- } elseif ($lhs === 'runtime') {
- $filters[] = new RuntimeStatisticsFilter($operator, $rhs);
- } elseif ($lhs === 'state') {
- $filters[] = new StateStatisticsFilter($operator, $rhs);
- } elseif ($lhs === 'hddgb') {
- $filters[] = new Id44StatisticsFilter($operator, $rhs);
- } elseif ($lhs === 'location') {
- $filters[] = new LocationStatisticsFilter($operator, $rhs);
- } elseif ($lhs === 'subnet') {
- $filters[] = new SubnetStatisticsFilter($operator, $rhs);
+ $operator = $data['op'];
+ $argument = $data['argument'];
+
+ if ($filterType === 'gbram') {
+ $filters[] = new RamGbStatisticsFilter($operator, $argument);
+ } elseif ($filterType === 'runtime') {
+ $filters[] = new RuntimeStatisticsFilter($operator, $argument);
+ } elseif ($filterType === 'state') {
+ $filters[] = new StateStatisticsFilter($operator, $argument);
+ } elseif ($filterType === 'hddgb') {
+ $filters[] = new Id44StatisticsFilter($operator, $argument);
+ } elseif ($filterType === 'location') {
+ $filters[] = new LocationStatisticsFilter($operator, $argument);
+ } elseif ($filterType === 'subnet') {
+ $filters[] = new SubnetStatisticsFilter($operator, $argument);
} else {
- if (array_key_exists($lhs, self::$columns) && self::$columns[$lhs]['column']) {
- $filters[] = new StatisticsFilter($lhs, $operator, $rhs);
+ if (array_key_exists($filterType, self::$columns)) {
+ $filters[] = new StatisticsFilter($filterType, $operator, $argument);
} else {
- Message::addError('invalid-filter-key', $lhs);
+ Message::addError('invalid-filter-key', $filterType);
}
}
}
@@ -152,18 +125,107 @@ class StatisticsFilter
return $filters;
}
+ private static function loadFilterFromGet()
+ {
+ $ops = Request::get('op', [], 'array');
+ $currentValues = ArrayUtil::mergeByKey([
+ 'filter' => Request::get('filter', [], 'array'),
+ 'op' => $ops,
+ 'argument' => Request::get('arg', [], 'array'),
+ ]);
+ if (Request::get('show') === false && empty($ops)) {
+ $currentValues['lastseen'] = [
+ 'filter' => true,
+ 'op' => '>',
+ 'argument' => gmdate('Y-m-d', strtotime('-30 day')),
+ ];
+ }
+ return $currentValues;
+ }
+
/**
* @param \StatisticsFilterSet $filterSet
*/
- public static function renderFilterBox($show, $filterSet, $query)
+ public static function renderFilterBox($show, $filterSet)
{
+ // Build location list, with permissions
+ $locs = [];
+ if (Module::isAvailable('locations')) {
+ $allowed = $filterSet->getAllowedLocations();
+ foreach (Location::getLocations(-1, 0, true) as $loc) {
+ $locs[] = [
+ 'key' => $loc['locationid'],
+ 'value' => $loc['locationpad'] . ' ' . $loc['locationname'],
+ 'disabled' => $allowed !== false && !in_array($loc['locationid'], $allowed)
+ ? 'disabled' : '',
+ ];
+ }
+ }
+ // Get current settings from GET
+ $currentValues = self::loadFilterFromGet();
+ // Build column array for rendering
+ $columns = [];
+ foreach (self::$columns as $key => $col) {
+ if ($key === 'location') {
+ $col['values'] = $locs;
+ }
+ $col['key'] = $key;
+ $col['name'] = Dictionary::translateFile('filters', $key, true);
+ if ($col['type'] === 'int') {
+ $col['input'] = 'number';
+ } elseif ($col['type'] === 'string') {
+ $col['input'] = 'text';
+ } elseif ($col['type'] === 'date') {
+ $col['input'] = 'text';
+ $col['inputclass'] = 'is-date';
+ } elseif ($col['type'] === 'enum') {
+ $col['enum'] = true;
+ if (isset($col['values'][0])) {
+ if (!is_array($col['values'][0])) {
+ // Arrayize
+ $col['values'] = array_map(function($e) { return [
+ 'key' => $e,
+ 'value' => $e,
+ ]; }, $col['values']);
+ }
+ } else {
+ $col['values'] = array_map(function($v, $k) { return [
+ 'key' => $k,
+ 'value' => $v,
+ ]; }, $col['values'], array_keys($col['values']));
+ }
+ if (isset($currentValues[$key]['argument'])) {
+ // Current value from GET
+ foreach ($col['values'] as &$value) {
+ if ($value['key'] == $currentValues[$key]['argument']) {
+ $value['selected'] = 'selected';
+ }
+ }
+ }
+ }
+ // current value from GET
+ if (isset($currentValues[$key])) {
+ $col['currentvalue'] = $currentValues[$key]['argument'] ?? '';
+ if ($currentValues[$key]['filter']) {
+ $col['checked'] = 'checked';
+ } elseif (!isset($col['show']) || !$col['show']) {
+ $col['collapse'] = 'collapse';
+ }
+ } elseif (!isset($col['show']) || !$col['show']) {
+ $col['collapse'] = 'collapse';
+ }
+ // Current value, arrayize
+ foreach ($col['op'] as &$value) {
+ $value = ['op' => $value];
+ if (($currentValues[$key]['op'] ?? '=') === $value['op']) {
+ $value['selected'] = 'selected';
+ }
+ }
+ $columns[] = $col;
+ }
$data = array(
'show' => $show,
- 'query' => $query,
- 'delimiter' => StatisticsFilter::DELIMITER,
- 'sortDirection' => $filterSet->getSortDirection(),
- 'sortColumn' => $filterSet->getSortColumn(),
- 'columns' => json_encode(StatisticsFilter::$columns),
+ 'columns' => $columns,
);
if ($show === 'list') {
@@ -175,42 +237,16 @@ class StatisticsFilter
}
- $locsFlat = array();
- if (Module::isAvailable('locations')) {
- $allowed = $filterSet->getAllowedLocations();
- foreach (Location::getLocations() as $loc) {
- $locsFlat['L' . $loc['locationid']] = array(
- 'pad' => $loc['locationpad'],
- 'name' => $loc['locationname'],
- 'disabled' => $allowed !== false && !in_array($loc['locationid'], $allowed),
- );
- }
- }
-
Permission::addGlobalTags($data['perms'], null, ['view.summary', 'view.list']);
- $data['locations'] = json_encode($locsFlat);
Render::addTemplate('filterbox', $data);
}
- private static $query = false;
-
- public static function getQuery()
- {
- if (self::$query === false) {
- self::$query = Request::any('filters', false, 'string');
- if (self::$query === false) {
- self::$query = 'lastseen > ' . gmdate('Y-m-d', strtotime('-30 day'));
- }
- }
- return self::$query;
- }
-
/*
* Simple filters that map directly to DB columns
*/
- const OP_ORDINAL = ['!=', '<=', '>=', '=', '<', '>'];
- const OP_STRCMP = ['!~', '~', '=', '!='];
+ const OP_ORDINAL = ['=', '!=', '<', '>', '<=', '>='];
+ const OP_STRCMP = [ '=', '!=', '!~', '~'];
const OP_NOMINAL = ['!=', '='];
public static $columns;
@@ -221,127 +257,123 @@ class StatisticsFilter
{
self::$columns = [
+ 'clientip' => [
+ 'op' => self::OP_NOMINAL,
+ 'type' => 'string',
+ 'placeholder' => '1.2.3.4',
+ 'show' => true,
+ ],
+ 'hostname' => [
+ 'op' => self::OP_STRCMP,
+ 'type' => 'string',
+ 'placeholder' => 'pc.fqdn.example.com',
+ ],
'machineuuid' => [
'op' => self::OP_NOMINAL,
'type' => 'string',
- 'column' => true,
+ 'placeholder' => '88888888-4444-4444-121212121212',
+ 'show' => true,
],
'macaddr' => [
'op' => self::OP_NOMINAL,
'type' => 'string',
- 'column' => true,
+ 'placeholder' => '11-22-33-44-55-66',
],
'firstseen' => [
'op' => self::OP_ORDINAL,
'type' => 'date',
- 'column' => true,
+ 'placeholder' => '2020-10-15',
],
'lastseen' => [
'op' => self::OP_ORDINAL,
'type' => 'date',
- 'column' => true,
+ 'placeholder' => '2020-10-15',
],
'logintime' => [
'op' => self::OP_ORDINAL,
'type' => 'date',
- 'column' => true,
+ 'placeholder' => '2020-10-15',
],
'lastboot' => [
'op' => self::OP_ORDINAL,
'type' => 'date',
- 'column' => true
+ 'placeholder' => '2020-10-15',
],
'runtime' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true
],
'realcores' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true,
],
'systemmodel' => [
'op' => self::OP_STRCMP,
'type' => 'string',
- 'column' => true,
+ 'placeholder' => 'PC-365 (IBM)',
],
'cpumodel' => [
'op' => self::OP_STRCMP,
'type' => 'string',
- 'column' => true,
+ 'placeholder' => 'Pentium Pro 200',
],
'hddgb' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => false,
+ 'placeholder' => 'GiB',
'map_sort' => 'id44mb'
],
'gbram' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
'map_sort' => 'mbram',
- 'column' => false,
+ 'placeholder' => 'GiB',
],
'kvmstate' => [
'op' => self::OP_NOMINAL,
'type' => 'enum',
- 'column' => true,
'values' => ['ENABLED', 'DISABLED', 'UNSUPPORTED']
],
'badsectors' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true
- ],
- 'clientip' => [
- 'op' => self::OP_NOMINAL,
- 'type' => 'string',
- 'column' => true
- ],
- 'hostname' => [
- 'op' => self::OP_STRCMP,
- 'type' => 'string',
- 'column' => true
],
'subnet' => [
'op' => self::OP_NOMINAL,
'type' => 'string',
- 'column' => false
],
'currentuser' => [
'op' => self::OP_NOMINAL,
'type' => 'string',
- 'column' => true
+ 'placeholder' => 'login',
],
'state' => [
'op' => self::OP_NOMINAL,
'type' => 'enum',
- 'column' => true,
'values' => ['occupied', 'on', 'off', 'idle', 'standby']
],
'live_swapfree' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true
+ 'placeholder' => 'MiB',
],
'live_memfree' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true
+ 'placeholder' => 'MiB',
],
'live_tmpfree' => [
'op' => self::OP_ORDINAL,
'type' => 'int',
- 'column' => true
+ 'placeholder' => 'MiB',
],
];
if (Module::isAvailable('locations')) {
self::$columns['location'] = [
'op' => self::OP_STRCMP,
'type' => 'enum',
- 'column' => false,
- 'values' => array_keys(Location::getLocationsAssoc()),
+ 'show' => true,
+ // values filled on render NOCOMMIT
];
}
}
@@ -534,4 +566,4 @@ class IsClientStatisticsFilter extends StatisticsFilter
}
-StatisticsFilter::initConstants(); \ No newline at end of file
+StatisticsFilter::initConstants();