update
This commit is contained in:
600
admin/templates/components/table-list.php
Normal file
600
admin/templates/components/table-list.php
Normal file
@@ -0,0 +1,600 @@
|
||||
<?php
|
||||
$list = $this->list;
|
||||
|
||||
$buildUrl = function(array $params = []) use ($list): string {
|
||||
$query = array_merge($list->query, $params);
|
||||
foreach ($query as $key => $value) {
|
||||
if ($value === '' || $value === null) {
|
||||
unset($query[$key]);
|
||||
}
|
||||
}
|
||||
$qs = http_build_query($query);
|
||||
return $list->basePath . $qs;
|
||||
};
|
||||
|
||||
$currentSort = $list->sort['column'] ?? '';
|
||||
$currentDir = strtoupper($list->sort['dir'] ?? 'DESC');
|
||||
$page = max(1, (int)($list->pagination['page'] ?? 1));
|
||||
$totalPages = max(1, (int)($list->pagination['total_pages'] ?? 1));
|
||||
$total = (int)($list->pagination['total'] ?? 0);
|
||||
$perPage = (int)($list->pagination['per_page'] ?? 15);
|
||||
|
||||
$hasActiveFilters = false;
|
||||
foreach ($list->filters as $filter) {
|
||||
if (isset($filter['value']) && (string)$filter['value'] !== '') {
|
||||
$hasActiveFilters = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$isCompactColumn = function(array $column): bool {
|
||||
$key = strtolower(trim((string)($column['key'] ?? '')));
|
||||
$label = strtolower(trim((string)($column['label'] ?? '')));
|
||||
|
||||
if (in_array($key, ['status', 'active', 'enabled', 'is_active', 'start', 'default'], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_array($label, ['status', 'aktywny', 'aktywnosc', 'active', 'domyslny', 'domyślny', 'default'], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
?>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<?php if (!empty($list->createUrl) && !empty($list->createLabel)): ?>
|
||||
<a href="<?= htmlspecialchars($list->createUrl, ENT_QUOTES, 'UTF-8'); ?>" class="btn btn-success btn-sm">
|
||||
<i class="fa fa-plus-circle mr5"></i><?= htmlspecialchars($list->createLabel, ENT_QUOTES, 'UTF-8'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col-sm-4 text-right">
|
||||
<div class="table-list-header-actions">
|
||||
<span class="text-muted">Wyników: <?= $total; ?></span>
|
||||
<?php if (!empty($list->filters)): ?>
|
||||
<button type="button" class="btn btn-default btn-sm js-filter-toggle-btn<?= $hasActiveFilters ? ' active' : ''; ?>" title="Filtry">
|
||||
<i class="fa fa-filter"></i>
|
||||
<?php if ($hasActiveFilters): ?>
|
||||
<span class="badge badge-primary table-filter-badge"><?= count(array_filter($list->filters, function($f) { return isset($f['value']) && (string)$f['value'] !== ''; })); ?></span>
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<div class="table-col-toggle-wrapper">
|
||||
<button type="button" class="btn btn-default btn-sm js-col-toggle-btn" title="Widoczność kolumn">
|
||||
<i class="fa fa-columns"></i>
|
||||
</button>
|
||||
<div class="table-col-toggle-dropdown js-col-toggle-dropdown">
|
||||
<div class="table-col-toggle-header">Widoczność kolumn</div>
|
||||
<?php foreach ($list->columns as $colIndex => $column): ?>
|
||||
<?php $colKey = (string)($column['key'] ?? 'col_' . $colIndex); ?>
|
||||
<label class="table-col-toggle-item">
|
||||
<span class="table-col-switch">
|
||||
<input type="checkbox" class="js-col-toggle-checkbox" data-col-key="<?= htmlspecialchars($colKey, ENT_QUOTES, 'UTF-8'); ?>" checked />
|
||||
<span class="table-col-switch-slider"></span>
|
||||
</span>
|
||||
<?= htmlspecialchars((string)($column['label'] ?? $colKey), ENT_QUOTES, 'UTF-8'); ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
<div class="table-col-toggle-footer">
|
||||
<button type="button" class="btn btn-default btn-xs js-col-toggle-reset">Pokaż wszystkie</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="js-table-filters-wrapper table-filters-wrapper<?= $hasActiveFilters ? ' open' : ''; ?>">
|
||||
<form method="get" action="<?= htmlspecialchars($list->basePath, ENT_QUOTES, 'UTF-8'); ?>" data-path-submit="<?= htmlspecialchars($list->basePath, ENT_QUOTES, 'UTF-8'); ?>" class="row mb15 js-table-filters-form">
|
||||
<?php foreach ($list->filters as $filter): ?>
|
||||
<?php
|
||||
$filterKey = (string)($filter['key'] ?? '');
|
||||
$inputId = 'filter_' . preg_replace('/[^a-zA-Z0-9_]+/', '_', $filterKey);
|
||||
$filterType = (string)($filter['type'] ?? '');
|
||||
$isCompactFilter = false;
|
||||
if ($filterType === 'select') {
|
||||
$options = (array)($filter['options'] ?? []);
|
||||
$maxOptionLen = 0;
|
||||
foreach ($options as $optionLabel) {
|
||||
$len = strlen(trim((string)$optionLabel));
|
||||
if ($len > $maxOptionLen) {
|
||||
$maxOptionLen = $len;
|
||||
}
|
||||
}
|
||||
|
||||
// Krotkie selekty (np. tak/nie) nie musza zajmowac szerokiej kolumny.
|
||||
$isCompactFilter = count($options) <= 5 && $maxOptionLen <= 12;
|
||||
}
|
||||
$filterColClass = $isCompactFilter ? 'col-sm-1 col-xs-6 mb10' : 'col-sm-2 mb10';
|
||||
?>
|
||||
<div class="<?= htmlspecialchars($filterColClass, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<label for="<?= htmlspecialchars($inputId, ENT_QUOTES, 'UTF-8'); ?>" class="control-label">
|
||||
<?= htmlspecialchars((string)($filter['label'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>
|
||||
</label>
|
||||
|
||||
<?php if ($filterType === 'select'): ?>
|
||||
<select
|
||||
id="<?= htmlspecialchars($inputId, ENT_QUOTES, 'UTF-8'); ?>"
|
||||
name="<?= htmlspecialchars($filter['key'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
class="form-control input-sm<?= $isCompactFilter ? ' js-filter-compact-select' : ''; ?>"
|
||||
<?= $isCompactFilter ? 'data-compact-filter="1"' : ''; ?>
|
||||
title="<?= htmlspecialchars($filter['label'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
>
|
||||
<?php foreach (($filter['options'] ?? []) as $value => $label): ?>
|
||||
<option value="<?= htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); ?>"<?= ((string)($filter['value'] ?? '') === (string)$value) ? ' selected="selected"' : ''; ?>>
|
||||
<?= htmlspecialchars((string)$label, ENT_QUOTES, 'UTF-8'); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php elseif (($filter['type'] ?? '') === 'date'): ?>
|
||||
<input
|
||||
type="date"
|
||||
id="<?= htmlspecialchars($inputId, ENT_QUOTES, 'UTF-8'); ?>"
|
||||
name="<?= htmlspecialchars($filter['key'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
value="<?= htmlspecialchars((string)($filter['value'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
class="form-control input-sm"
|
||||
title="<?= htmlspecialchars($filter['label'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
/>
|
||||
<?php else: ?>
|
||||
<input
|
||||
type="text"
|
||||
id="<?= htmlspecialchars($inputId, ENT_QUOTES, 'UTF-8'); ?>"
|
||||
name="<?= htmlspecialchars($filter['key'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
value="<?= htmlspecialchars((string)($filter['value'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
class="form-control input-sm"
|
||||
placeholder="<?= htmlspecialchars($filter['label'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
title="<?= htmlspecialchars($filter['label'], ENT_QUOTES, 'UTF-8'); ?>"
|
||||
/>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<input type="hidden" name="sort" value="<?= htmlspecialchars((string)$currentSort, ENT_QUOTES, 'UTF-8'); ?>" />
|
||||
<input type="hidden" name="dir" value="<?= htmlspecialchars((string)$currentDir, ENT_QUOTES, 'UTF-8'); ?>" />
|
||||
<input type="hidden" name="per_page" value="<?= $perPage; ?>" />
|
||||
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm">Szukaj</button>
|
||||
<a href="<?= htmlspecialchars($list->basePath, ENT_QUOTES, 'UTF-8'); ?>" class="btn btn-default btn-sm js-table-filters-clear">Wyczyść</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-striped table-bordered mbn table-list-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach ($list->columns as $colIndex => $column): ?>
|
||||
<?php
|
||||
$colKey = (string)($column['key'] ?? 'col_' . $colIndex);
|
||||
$sortKey = (string)($column['sort_key'] ?? ($column['key'] ?? ''));
|
||||
$isAllowedSortKey = empty($list->sortableColumns) || in_array($sortKey, $list->sortableColumns, true);
|
||||
$isSortable = !empty($column['sortable']) && $sortKey !== '' && $isAllowedSortKey;
|
||||
$isCurrent = $isSortable && $currentSort === $sortKey;
|
||||
$nextDir = ($isCurrent && $currentDir === 'ASC') ? 'DESC' : 'ASC';
|
||||
$sortUrl = $buildUrl([
|
||||
'sort' => $sortKey,
|
||||
'dir' => $nextDir,
|
||||
'page' => 1,
|
||||
]);
|
||||
$headerClass = trim((string)($column['class'] ?? ''));
|
||||
if ($isCompactColumn($column)) {
|
||||
$headerClass = trim($headerClass . ' table-col-compact');
|
||||
}
|
||||
?>
|
||||
<th class="<?= htmlspecialchars($headerClass, ENT_QUOTES, 'UTF-8'); ?>" data-col-key="<?= htmlspecialchars($colKey, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<?php if ($isSortable): ?>
|
||||
<a href="<?= htmlspecialchars($sortUrl, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<?= htmlspecialchars((string)($column['label'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>
|
||||
<?php if ($isCurrent): ?>
|
||||
<span aria-hidden="true"><?= $currentDir === 'ASC' ? '↑' : '↓'; ?></span>
|
||||
<?php else: ?>
|
||||
<span class="text-muted" aria-hidden="true">↕</span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<?= htmlspecialchars((string)($column['label'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<?php endforeach; ?>
|
||||
<th class="text-center" style="width: 160px;">Akcje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (is_array($list->rows) && !empty($list->rows)): ?>
|
||||
<?php foreach ($list->rows as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($list->columns as $colIndex => $column): ?>
|
||||
<?php
|
||||
$key = $column['key'] ?? '';
|
||||
$colKey = (string)($column['key'] ?? 'col_' . $colIndex);
|
||||
$raw = !empty($column['raw']);
|
||||
$value = $row[$key] ?? '';
|
||||
$cellClass = trim((string)($column['class'] ?? ''));
|
||||
if ($isCompactColumn($column)) {
|
||||
$cellClass = trim($cellClass . ' table-col-compact');
|
||||
}
|
||||
?>
|
||||
<td class="<?= htmlspecialchars($cellClass, ENT_QUOTES, 'UTF-8'); ?>" data-col-key="<?= htmlspecialchars($colKey, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<?php if ($raw): ?>
|
||||
<?= (string)$value; ?>
|
||||
<?php else: ?>
|
||||
<?= htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<td class="text-center">
|
||||
<?php foreach (($row['_actions'] ?? []) as $action): ?>
|
||||
<?php
|
||||
$confirmMessage = (string)($action['confirm'] ?? '');
|
||||
$needsConfirm = $confirmMessage !== '';
|
||||
$actionClass = (string)($action['class'] ?? 'btn btn-default btn-xs');
|
||||
if ($needsConfirm) {
|
||||
$actionClass .= ' js-table-action-confirm';
|
||||
}
|
||||
?>
|
||||
<a
|
||||
href="<?= htmlspecialchars((string)($action['url'] ?? '#'), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
class="<?= htmlspecialchars($actionClass, ENT_QUOTES, 'UTF-8'); ?>"
|
||||
<?php if ($needsConfirm): ?>
|
||||
data-confirm-title="Potwierdzenie"
|
||||
data-confirm-message="<?= htmlspecialchars($confirmMessage, ENT_QUOTES, 'UTF-8'); ?>"
|
||||
data-confirm-ok="<?= htmlspecialchars((string)($action['confirm_ok'] ?? 'Usun'), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
data-confirm-cancel="<?= htmlspecialchars((string)($action['confirm_cancel'] ?? 'Anuluj'), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
<?php endif; ?>
|
||||
>
|
||||
<?= htmlspecialchars((string)($action['label'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="<?= count($list->columns) + 1; ?>">
|
||||
<div class="alert alert-danger mbn"><?= htmlspecialchars((string)$list->emptyMessage, ENT_QUOTES, 'UTF-8'); ?></div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="row mt15">
|
||||
<div class="col-sm-6">
|
||||
<ul class="pagination">
|
||||
<?php $prevPage = max(1, $page - 1); ?>
|
||||
<?php $nextPage = min($totalPages, $page + 1); ?>
|
||||
<li class="<?= $page <= 1 ? 'disabled' : ''; ?>">
|
||||
<a href="<?= htmlspecialchars($buildUrl(['page' => 1]), ENT_QUOTES, 'UTF-8'); ?>"><i class="fa fa-fast-backward"></i></a>
|
||||
</li>
|
||||
<li class="<?= $page <= 1 ? 'disabled' : ''; ?>">
|
||||
<a href="<?= htmlspecialchars($buildUrl(['page' => $prevPage]), ENT_QUOTES, 'UTF-8'); ?>"><i class="fa fa-backward"></i></a>
|
||||
</li>
|
||||
<?php for ($i = max(1, $page - 3); $i <= min($totalPages, $page + 3); $i++): ?>
|
||||
<li class="<?= $i === $page ? 'active' : ''; ?>">
|
||||
<a href="<?= htmlspecialchars($buildUrl(['page' => $i]), ENT_QUOTES, 'UTF-8'); ?>"><?= $i; ?></a>
|
||||
</li>
|
||||
<?php endfor; ?>
|
||||
<li class="<?= $page >= $totalPages ? 'disabled' : ''; ?>">
|
||||
<a href="<?= htmlspecialchars($buildUrl(['page' => $nextPage]), ENT_QUOTES, 'UTF-8'); ?>"><i class="fa fa-forward"></i></a>
|
||||
</li>
|
||||
<li class="<?= $page >= $totalPages ? 'disabled' : ''; ?>">
|
||||
<a href="<?= htmlspecialchars($buildUrl(['page' => $totalPages]), ENT_QUOTES, 'UTF-8'); ?>"><i class="fa fa-fast-forward"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<form method="get" action="<?= htmlspecialchars($list->basePath, ENT_QUOTES, 'UTF-8'); ?>" data-path-submit="<?= htmlspecialchars($list->basePath, ENT_QUOTES, 'UTF-8'); ?>" class="form-inline table-list-per-page-form">
|
||||
<?php foreach ($list->query as $key => $value): ?>
|
||||
<?php if ($key !== 'per_page' && $key !== 'page'): ?>
|
||||
<input type="hidden" name="<?= htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); ?>" value="<?= htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); ?>" />
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<input type="hidden" name="page" value="1" />
|
||||
Wyświetlaj
|
||||
<select name="per_page" class="form-control input-sm js-per-page-select">
|
||||
<?php foreach ($list->perPageOptions as $opt): ?>
|
||||
<option value="<?= (int)$opt; ?>"<?= ((int)$opt === $perPage) ? ' selected="selected"' : ''; ?>><?= (int)$opt; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
rekordów
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Table state persistence — redirect ASAP to saved view
|
||||
(function() {
|
||||
var basePath = <?= json_encode($list->basePath); ?>;
|
||||
var stateKey = 'tableListQuery_' + basePath;
|
||||
var clearKey = 'tableListCleared_' + basePath;
|
||||
|
||||
var pathname = window.location.pathname.replace(/\/+$/, '/');
|
||||
var bp = basePath.replace(/\/+$/, '/');
|
||||
|
||||
var queryPart = '';
|
||||
if (pathname.length > bp.length && pathname.indexOf(bp) === 0) {
|
||||
queryPart = pathname.substring(bp.length);
|
||||
}
|
||||
if (!queryPart && window.location.search) {
|
||||
queryPart = window.location.search.substring(1);
|
||||
}
|
||||
|
||||
try {
|
||||
var justCleared = sessionStorage.getItem(clearKey) === '1';
|
||||
sessionStorage.removeItem(clearKey);
|
||||
|
||||
if (queryPart) {
|
||||
localStorage.setItem(stateKey, queryPart);
|
||||
} else if (!justCleared) {
|
||||
var saved = localStorage.getItem(stateKey);
|
||||
if (saved) {
|
||||
window.location.replace(basePath + saved);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
if (!$) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(document).off('click.tableListConfirm', '.js-table-action-confirm');
|
||||
$(document).on('click.tableListConfirm', '.js-table-action-confirm', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $link = $(this);
|
||||
var href = $link.attr('href');
|
||||
var title = $link.data('confirmTitle') || 'Potwierdzenie';
|
||||
var message = $link.data('confirmMessage') || 'Czy na pewno chcesz kontynuowac?';
|
||||
var okLabel = $link.data('confirmOk') || 'Usun';
|
||||
var cancelLabel = $link.data('confirmCancel') || 'Anuluj';
|
||||
|
||||
if (!href) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof $.confirm === 'function') {
|
||||
$.confirm({
|
||||
title: String(title),
|
||||
content: String(message),
|
||||
type: 'red',
|
||||
boxWidth: '560px',
|
||||
useBootstrap: false,
|
||||
animation: 'scale',
|
||||
closeAnimation: 'scale',
|
||||
backgroundDismissAnimation: 'shake',
|
||||
container: 'body',
|
||||
theme: 'modern',
|
||||
columnClass: '',
|
||||
typeAnimated: true,
|
||||
lazyOpen: false,
|
||||
draggable: false,
|
||||
closeIcon: true,
|
||||
containerFluid: true,
|
||||
escapeKey: true,
|
||||
backgroundDismiss: true,
|
||||
animationBounce: 1.1,
|
||||
watchInterval: 100,
|
||||
offsetTop: 0,
|
||||
offsetBottom: 0,
|
||||
customClass: 'table-list-confirm-dialog',
|
||||
buttons: {
|
||||
cancel: {
|
||||
text: String(cancelLabel),
|
||||
btnClass: 'btn-default'
|
||||
},
|
||||
confirm: {
|
||||
text: String(okLabel),
|
||||
btnClass: 'btn-danger',
|
||||
action: function() {
|
||||
window.location.href = href;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window.confirm(String(message))) {
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).off(
|
||||
'change.tableListAutoFilter',
|
||||
'.js-table-filters-form select, .js-table-filters-form input[type="date"], .js-table-filters-form input[type="text"]'
|
||||
);
|
||||
$(document).on(
|
||||
'change.tableListAutoFilter',
|
||||
'.js-table-filters-form select, .js-table-filters-form input[type="date"], .js-table-filters-form input[type="text"]',
|
||||
function() {
|
||||
var form = $(this).closest('form');
|
||||
if (form.length) {
|
||||
form.trigger('submit');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// --- Column visibility toggle ---
|
||||
var storageKey = 'tableListCols_' + <?= json_encode($list->basePath); ?>;
|
||||
|
||||
function getHiddenCols() {
|
||||
try {
|
||||
var data = localStorage.getItem(storageKey);
|
||||
if (data) {
|
||||
var parsed = JSON.parse(data);
|
||||
if (Array.isArray(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
return [];
|
||||
}
|
||||
|
||||
function saveHiddenCols(hiddenArr) {
|
||||
try {
|
||||
localStorage.setItem(storageKey, JSON.stringify(hiddenArr));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function applyColumnVisibility(hiddenCols) {
|
||||
var $table = $('.table-list-table');
|
||||
$table.find('th[data-col-key], td[data-col-key]').each(function() {
|
||||
var key = $(this).attr('data-col-key');
|
||||
if (hiddenCols.indexOf(key) !== -1) {
|
||||
$(this).addClass('table-col-hidden');
|
||||
} else {
|
||||
$(this).removeClass('table-col-hidden');
|
||||
}
|
||||
});
|
||||
|
||||
$('.js-col-toggle-checkbox').each(function() {
|
||||
var key = $(this).attr('data-col-key');
|
||||
$(this).prop('checked', hiddenCols.indexOf(key) === -1);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply saved state on load
|
||||
var hiddenCols = getHiddenCols();
|
||||
if (hiddenCols.length) {
|
||||
applyColumnVisibility(hiddenCols);
|
||||
}
|
||||
|
||||
// Toggle dropdown open/close
|
||||
$(document).off('click.colToggleBtn', '.js-col-toggle-btn');
|
||||
$(document).on('click.colToggleBtn', '.js-col-toggle-btn', function(e) {
|
||||
e.stopPropagation();
|
||||
var $dropdown = $(this).siblings('.js-col-toggle-dropdown');
|
||||
$dropdown.toggleClass('open');
|
||||
});
|
||||
|
||||
// Prevent closing when clicking inside dropdown
|
||||
$(document).off('click.colToggleDropdown', '.js-col-toggle-dropdown');
|
||||
$(document).on('click.colToggleDropdown', '.js-col-toggle-dropdown', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Close dropdown on outside click
|
||||
$(document).off('click.colToggleClose');
|
||||
$(document).on('click.colToggleClose', function() {
|
||||
$('.js-col-toggle-dropdown').removeClass('open');
|
||||
});
|
||||
|
||||
// Checkbox change — toggle column
|
||||
$(document).off('change.colToggle', '.js-col-toggle-checkbox');
|
||||
$(document).on('change.colToggle', '.js-col-toggle-checkbox', function() {
|
||||
var key = $(this).attr('data-col-key');
|
||||
var isChecked = $(this).is(':checked');
|
||||
var current = getHiddenCols();
|
||||
|
||||
if (isChecked) {
|
||||
current = $.grep(current, function(v) { return v !== key; });
|
||||
} else {
|
||||
if (current.indexOf(key) === -1) {
|
||||
current.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
saveHiddenCols(current);
|
||||
applyColumnVisibility(current);
|
||||
});
|
||||
|
||||
// Reset — show all columns
|
||||
$(document).off('click.colToggleReset', '.js-col-toggle-reset');
|
||||
$(document).on('click.colToggleReset', '.js-col-toggle-reset', function() {
|
||||
saveHiddenCols([]);
|
||||
applyColumnVisibility([]);
|
||||
});
|
||||
|
||||
// --- Filter toggle ---
|
||||
var filterStorageKey = 'tableListFilters_' + <?= json_encode($list->basePath); ?>;
|
||||
|
||||
function isFilterVisible() {
|
||||
try {
|
||||
return localStorage.getItem(filterStorageKey) === '1';
|
||||
} catch (e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
function saveFilterState(visible) {
|
||||
try {
|
||||
localStorage.setItem(filterStorageKey, visible ? '1' : '0');
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
var $filterWrapper = $('.js-table-filters-wrapper');
|
||||
var $filterBtn = $('.js-filter-toggle-btn');
|
||||
var hasActiveFilters = $filterWrapper.hasClass('open');
|
||||
|
||||
if (!hasActiveFilters && isFilterVisible()) {
|
||||
$filterWrapper.addClass('open');
|
||||
$filterBtn.addClass('active');
|
||||
}
|
||||
|
||||
$(document).off('click.filterToggle', '.js-filter-toggle-btn');
|
||||
$(document).on('click.filterToggle', '.js-filter-toggle-btn', function() {
|
||||
var $wrapper = $('.js-table-filters-wrapper');
|
||||
var $btn = $(this);
|
||||
var isOpen = $wrapper.hasClass('open');
|
||||
|
||||
if (isOpen) {
|
||||
$wrapper.removeClass('open');
|
||||
$btn.removeClass('active');
|
||||
saveFilterState(false);
|
||||
} else {
|
||||
$wrapper.addClass('open');
|
||||
$btn.addClass('active');
|
||||
saveFilterState(true);
|
||||
}
|
||||
});
|
||||
|
||||
// --- Path-based form submission (admin URL routing) ---
|
||||
$(document).off('submit.tablePathSubmit', 'form[data-path-submit]');
|
||||
$(document).on('submit.tablePathSubmit', 'form[data-path-submit]', function(e) {
|
||||
e.preventDefault();
|
||||
var basePath = $(this).attr('data-path-submit');
|
||||
var data = $(this).serializeArray();
|
||||
var parts = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (String(data[i].value) !== '') {
|
||||
parts.push(encodeURIComponent(data[i].name) + '=' + encodeURIComponent(data[i].value));
|
||||
}
|
||||
}
|
||||
window.location.href = basePath + (parts.length ? parts.join('&') : '');
|
||||
});
|
||||
|
||||
// Per-page select auto-submit
|
||||
$(document).off('change.tablePerPage', '.js-per-page-select');
|
||||
$(document).on('change.tablePerPage', '.js-per-page-select', function() {
|
||||
$(this).closest('form').trigger('submit');
|
||||
});
|
||||
|
||||
// --- Table state clear on "Wyczyść" ---
|
||||
var stateStorageKey = 'tableListQuery_' + <?= json_encode($list->basePath); ?>;
|
||||
var stateClearKey = 'tableListCleared_' + <?= json_encode($list->basePath); ?>;
|
||||
|
||||
$(document).off('click.tableClearState', '.js-table-filters-clear');
|
||||
$(document).on('click.tableClearState', '.js-table-filters-clear', function() {
|
||||
try {
|
||||
localStorage.removeItem(stateStorageKey);
|
||||
sessionStorage.setItem(stateClearKey, '1');
|
||||
} catch (e) {}
|
||||
});
|
||||
})(window.jQuery);
|
||||
</script>
|
||||
Reference in New Issue
Block a user