diff options
author | Simon Rettberg | 2020-04-20 11:49:17 +0200 |
---|---|---|
committer | Simon Rettberg | 2020-04-20 11:49:17 +0200 |
commit | 5eaa4292c6db2c1ee1282c938c899dc5b88db65f (patch) | |
tree | 137eaa063302b055ddec03e2c4c3ff5c084f11bf /modules-available/statistics/inc | |
parent | [serversetup-bwlp-ipxe] Fix: Imported PXELINUX entries are invalid (diff) | |
download | slx-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.php | 270 |
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(); |