130 lines
4.6 KiB
PHP
130 lines
4.6 KiB
PHP
<?php
|
|
|
|
if (!function_exists('sortable_table_format_bytes')) {
|
|
function sortable_table_format_bytes($bytes, $disk = false)
|
|
{
|
|
if ($bytes === null || $bytes === '') return '--';
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
$value = (float)$bytes;
|
|
$unitIndex = 0;
|
|
while (abs($value) >= 1024 && $unitIndex < count($units) - 1) {
|
|
$value /= 1024;
|
|
$unitIndex += 1;
|
|
}
|
|
$decimals = $disk ? ($unitIndex >= 4 ? 2 : ($unitIndex >= 1 ? 1 : 0)) : ($unitIndex === 0 ? 0 : 1);
|
|
return number_format($value, $decimals) . ' ' . $units[$unitIndex];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('sortable_table_format_value')) {
|
|
function sortable_table_format_value($value, $row, $column)
|
|
{
|
|
$format = $column['format'] ?? null;
|
|
if (is_callable($format)) {
|
|
return [$format($value, $row, $column), $value];
|
|
}
|
|
|
|
switch ($format) {
|
|
case 'number':
|
|
return [number_format((float)$value), (float)$value];
|
|
case 'bytes':
|
|
return [sortable_table_format_bytes($value, false), (float)$value];
|
|
case 'disk-bytes':
|
|
return [sortable_table_format_bytes($value, true), (float)$value];
|
|
case 'percent':
|
|
return [number_format((float)$value, 1) . '%', (float)$value];
|
|
case 'duration-ms':
|
|
$number = (float)$value;
|
|
if ($number >= 1000) {
|
|
return [number_format($number / 1000, $number >= 10000 ? 0 : 1) . ' s', $number];
|
|
}
|
|
return [number_format($number, $number >= 100 ? 0 : 1) . ' ms', $number];
|
|
case 'bool':
|
|
return [$value ? 'Yes' : 'No', $value ? 1 : 0];
|
|
default:
|
|
if (is_bool($value)) {
|
|
return [$value ? 'Yes' : 'No', $value ? 1 : 0];
|
|
}
|
|
return [(string)$value, is_scalar($value) ? $value : ''];
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'render' => function($prop) {
|
|
include_js('js/u-format.js');
|
|
include_js('js/u-sortable-table.js');
|
|
|
|
$tableId = (string)($prop['id'] ?? ('sortable-table-' . uniqid()));
|
|
$title = (string)($prop['title'] ?? '');
|
|
$subtitle = (string)($prop['subtitle'] ?? '');
|
|
$columns = is_array($prop['columns'] ?? null) ? $prop['columns'] : [];
|
|
$rows = is_array($prop['rows'] ?? null) ? $prop['rows'] : [];
|
|
$emptyLabel = (string)($prop['empty_label'] ?? 'No data available');
|
|
$storageKey = (string)($prop['storage_key'] ?? ('starter.sort.' . $tableId));
|
|
$sort = is_array($prop['sort'] ?? null) ? $prop['sort'] : [];
|
|
$initOptions = ['storageKey' => $storageKey];
|
|
if (isset($sort['column'])) {
|
|
$initOptions['initialSort'] = [
|
|
'column' => (int)$sort['column'],
|
|
'direction' => (($sort['direction'] ?? 'asc') === 'desc') ? 'desc' : 'asc',
|
|
];
|
|
}
|
|
$jsonFlags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT;
|
|
ob_start();
|
|
?>
|
|
<div class="dashboard-panel">
|
|
<?php if ($title !== '' || $subtitle !== ''): ?>
|
|
<div class="dashboard-panel-header">
|
|
<?php if ($title !== ''): ?><h2><?= safe($title) ?></h2><?php endif; ?>
|
|
<?php if ($subtitle !== ''): ?><p><?= safe($subtitle) ?></p><?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="dashboard-table-wrap">
|
|
<table id="<?= asafe($tableId) ?>" class="u-sortable-table">
|
|
<thead>
|
|
<tr>
|
|
<?php foreach ($columns as $column): ?>
|
|
<?php
|
|
$align = (string)($column['align'] ?? 'left');
|
|
$sortable = !isset($column['sortable']) || $column['sortable'];
|
|
?>
|
|
<th scope="col" class="align-<?= asafe($align) ?>"<?= !$sortable ? ' data-sortable="false"' : '' ?>><?= safe((string)($column['label'] ?? $column['key'] ?? 'Column')) ?></th>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (!$rows): ?>
|
|
<tr data-empty-row="1"><td colspan="<?= count($columns) ?: 1 ?>" class="muted"><?= safe($emptyLabel) ?></td></tr>
|
|
<?php endif; ?>
|
|
<?php foreach ($rows as $row): ?>
|
|
<tr>
|
|
<?php foreach ($columns as $column): ?>
|
|
<?php
|
|
$key = (string)($column['key'] ?? '');
|
|
$value = $row[$key] ?? '';
|
|
list($displayValue, $sortValue) = sortable_table_format_value($value, $row, $column);
|
|
if (isset($column['sort_value']) && is_callable($column['sort_value'])) {
|
|
$sortValue = $column['sort_value']($value, $row, $column);
|
|
}
|
|
?>
|
|
<td class="align-<?= asafe((string)($column['align'] ?? 'left')) ?>" data-sort-value="<?= asafe((string)$sortValue) ?>"><?= safe((string)$displayValue) ?></td>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
if (typeof USortableTable === 'undefined') return;
|
|
USortableTable.init(<?= jsafe($tableId) ?>, <?= json_encode($initOptions, $jsonFlags) ?>);
|
|
}());
|
|
</script>
|
|
<?php
|
|
return ob_get_clean();
|
|
},
|
|
|
|
'about' => 'Lightweight sortable HTML table with remembered sort state and human-readable data formatting',
|
|
];
|