refactor: reimplement command palette using a custom overlay instead of the native dialog element
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
'orderable' => $c['orderable'] ?? true,
|
||||
'searchable' => $c['searchable'] ?? true,
|
||||
'visible' => $c['visible'] ?? true,
|
||||
'key' => $c['key'],
|
||||
'label' => $c['label'],
|
||||
];
|
||||
})->values();
|
||||
@endphp
|
||||
@@ -29,40 +31,106 @@
|
||||
</div>
|
||||
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="{{ $id }}-column-offcanvas">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title">Column Visibility</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
@foreach($columns as $index => $col)
|
||||
@if((!isset($col['visibility']) || $col['visibility'] !== false) && $col['key'] !== 'checkbox')
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input type="checkbox" class="form-check-input column-toggle"
|
||||
data-column-index="{{ $index }}"
|
||||
id="{{ $id }}-col-{{ $index }}"
|
||||
{{ !isset($col['visible']) || $col['visible'] !== false ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="{{ $id }}-col-{{ $index }}">{!! $col['label'] !!}</label>
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 class="offcanvas-title">Column Visibility</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<p class="text-muted small mb-3"><i class="ti ti-arrows-sort me-1"></i> Drag to reorder columns</p>
|
||||
<div id="{{ $id }}-column-list">
|
||||
@foreach($columns as $index => $col)
|
||||
@if((!isset($col['visibility']) || $col['visibility'] !== false) && $col['key'] !== 'checkbox')
|
||||
<div class="form-check form-switch mb-2 p-2 rounded cursor-move column-item" data-column-key="{{ $col['key'] }}" data-column-index="{{ $index }}">
|
||||
<input type="checkbox" class="form-check-input column-toggle"
|
||||
data-column-key="{{ $col['key'] }}"
|
||||
data-column-index="{{ $index }}"
|
||||
id="{{ $id }}-col-{{ $index }}"
|
||||
{{ !isset($col['visible']) || $col['visible'] !== false ? 'checked' : '' }}>
|
||||
<label class="form-check-label user-select-none" for="{{ $id }}-col-{{ $index }}">{{ $col['label'] }}</label>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('custom-scripts')
|
||||
<script src="{{ asset('build/plugins/sortablejs/Sortable.min.js') }}"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var dtColumns = @json($dtColumns);
|
||||
var table = $('#{{ $id }}').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
ajax: '{{ $ajax }}',
|
||||
columns: @json($dtColumns),
|
||||
columns: dtColumns,
|
||||
colReorder: true,
|
||||
});
|
||||
|
||||
$('#{{ $id }}-column-offcanvas').on('change', '.column-toggle', function () {
|
||||
var columnIdx = $(this).data('column-index');
|
||||
var column = table.column(columnIdx);
|
||||
column.visible($(this).is(':checked'));
|
||||
var columnKey = $(this).data('column-key');
|
||||
var colIdx = -1;
|
||||
dtColumns.forEach(function(col, idx) {
|
||||
if (col.key === columnKey) {
|
||||
colIdx = idx;
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (colIdx >= 0) {
|
||||
var column = table.column(colIdx);
|
||||
column.visible($(this).is(':checked'));
|
||||
}
|
||||
});
|
||||
|
||||
var sortableInstance = null;
|
||||
|
||||
function initSortable() {
|
||||
var sortableList = document.getElementById('{{ $id }}-column-list');
|
||||
if (!sortableList) {
|
||||
console.log('Sortable list not found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (sortableInstance) {
|
||||
sortableInstance.destroy();
|
||||
}
|
||||
|
||||
console.log('Initializing Sortable');
|
||||
sortableInstance = new Sortable(sortableList, {
|
||||
animation: 150,
|
||||
ghostClass: 'bg-light',
|
||||
onEnd: function (evt) {
|
||||
var items = sortableList.querySelectorAll('.column-item');
|
||||
var newOrder = [];
|
||||
items.forEach(function(item) {
|
||||
newOrder.push(parseInt(item.dataset.columnIndex));
|
||||
});
|
||||
console.log('New order:', newOrder);
|
||||
table.colReorder.order(newOrder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var offcanvasEl = document.getElementById('{{ $id }}-column-offcanvas');
|
||||
if (offcanvasEl) {
|
||||
offcanvasEl.addEventListener('shown.bs.offcanvas', function() {
|
||||
console.log('Offcanvas shown, initializing sortable');
|
||||
initSortable();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.column-item {
|
||||
cursor: move;
|
||||
transition: background-color 0.15s;
|
||||
}
|
||||
.column-item:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.column-item:active {
|
||||
cursor: moving;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
Reference in New Issue
Block a user