Perbaikan data desa tidak tampil / tidak sesuai filter saat membuka halaman Desa dari Dasbor - #1266
Merged
Merged
Conversation
|
🔄 AI PR Review sedang antri di server...
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
issue # #1265
🎯 Deskripsi
Pull request ini memperbaiki bug pada alur navigasi dari Dasbor menuju halaman Data Desa (
/desa), di mana daftar desa pada DataTable tidak menampilkan data yang sesuai dengan parameter filter yang dikirim (bahkan tabel bisa kosong sama sekali).Terdapat tiga akar masalah yang diperbaiki:
Parameter
filter[kode_desa]=nullterkirim sebagai string literal. Handler klik "Selengkapnya" pada kartu dasbor memanggilURLSearchParams.set()untuk semua key filter termasuk yang kosong. Karenaset(name, null)mengonversinullmenjadi string"null", URL yang dihasilkan berisifilter[kode_desa]=null. Controller kemudian merender<option value="null">pada select desa, dan request DataTable mengirim nilai"null"tersebut sehingga exact match filter desa di API gagal.DataTable halaman desa mengirim
sort=undefined. Konfigurasi tabel memakaiordering: truetanpaorderawal, sehingga DataTables memakai default[[0, 'asc']]pada kolom No yang tidak memilikiname. Akibatnya parametersortdihitung menjadi"undefined"pada setiap request, ditolak oleh API (spatie QueryBuilderallowedSorts) dengan status400, dan tabel tidak pernah menampilkan data.Filter kecamatan/desa dari URL hilang setelah halaman dimuat. Script wilayah filter men-trigger ulang select kabupaten secara asynchronous saat memuat daftar kabupaten. Cascade
empty()pada handlerchangemenghapus opsi kecamatan/desa yang sudah dirender server dari parameter URL. Selain itu,isAutoLoadmengeklik#bt_filteryang tidak ada di halaman desa (tombol filternya bernama#filter), sehingga DataTable tidak pernah di-redraw dengan filter hasil restore.🛠️ Perubahan yang Dilakukan
1.
resources/views/dasbor/summary.blade.phpFix — Hanya mengirim parameter filter yang terisi saat klik "Selengkapnya":
data('filter')pada kartu dinormalisasi dengan|| ''agar tidak pernah bernilainull.searchParams.set()untuk key yang tidak kosong, sehingga URL tidak lagi memuatfilter[kode_desa]=null..data( 'filter', { - 'kode_kabupaten': kabupaten, - 'kode_kecamatan': kecamatan, - 'kode_desa': desa, + 'kode_kabupaten': kabupaten || '', + 'kode_kecamatan': kecamatan || '', + 'kode_desa': desa || '',2.
app/Http/Controllers/DesaController.phpFix — Normalisasi nilai filter string
"null"/"undefined"menjadinull:value="null"dan DataTable tidak mengirim nilai"null"sebagai filter.$filters = request('filter', [ 'kode_kabupaten' => null, 'kode_desa' => null, 'kode_kecamatan' => null, ]); + $filters = collect($filters)->map(function ($value) { + return in_array($value, ['null', 'undefined'], true) ? null : $value; + })->all(); + return view('desa.index', compact('filters'));3.
resources/views/desa/index.blade.phpFix — Konfigurasi DataTable halaman desa:
order: [[1, 'asc']](urutkan berdasarkan nama desa) sehingga request pertama mengirimsort=nama_desayang valid, bukansort=undefined.headers: header(Bearer token API) agar konsisten dengan halaman lain (penduduk/keluarga).|| ''agar tidak mengirim nilainull/undefined.sort: hanya dikirim jika kolom target memilikiname(selain itu di-skip).columnDefsorderable: falsedipersempit hanya untuk kolom No (target0); kolom nama desa, nama kecamatan, dan jumlah penduduk tetap dapat diurutkan sesuai desain awal fitur sort.autoWidth: false, ordering: true, + order: [ + [1, 'asc'] + ],ajax: { url: urlPenduduk, + headers: header, method: 'get', data: function(row) { return { "page[size]": row.length, "page[number]": (row.start / row.length) + 1, "filter[search]": row.search.value, - "filter[kode_kabupaten]": $("#filter_kabupaten").val(), - "filter[kode_kecamatan]": $("#filter_kecamatan").val(), - "filter[kode_desa]": $("#filter_desa").val(), - "sort": (row.order[0]?.dir === "asc" ? "" : "-") + row.columns[row + "filter[kode_kabupaten]": $("#filter_kabupaten").val() || '', + "filter[kode_kecamatan]": $("#filter_kecamatan").val() || '', + "filter[kode_desa]": $("#filter_desa").val() || '', + "sort": row.columns[row.order[0]?.column]?.name ? + (row.order[0]?.dir === "asc" ? "" : "-") + row.columns[row .order[0] ?.column] - ?.name + ?.name : undefined{ - targets: [0, 1, 2, 3], + targets: 0, orderable: false, searchable: false, },$(document).on('click', '#reset', function(e) { e.preventDefault(); $('#filter_kabupaten').val('').change(); - $('#filter_kabupaten').val('').change(); - $('#filter_kabupaten').val('').change(); + $('#filter_kecamatan').val('').change(); + $('#filter_desa').val('').change(); pendudukDatatable.ajax.reload(); });4.
resources/views/components/wilayah_filter_js.blade.phpFix — Restore filter dari URL dan redraw tabel setelah cascade selesai:
queryKodeKabupaten,queryKodeKecamatan, danqueryKodeDesadibaca dariwindow.location.searchdi scope top-level handler (sebelumnyaqueryKodeKabupatenhanya tersedia di dalam callback kabupaten).urlFilterRestoringyang hanya aktif saat kabupaten di-restore dari URL, sehingga pemilihan kecamatan/desa dari URL tidak mengganggu alur normal.filter[kode_kecamatan]dari URL lalutrigger('change'); pola yang sama diterapkan untuk desa (filter[kode_desa]).isAutoLoadkini mengeklik#bt_filter, #filtersekaligus — halaman desa yang memiliki tombol filter#filterikut ter-redraw dengan nilai filter hasil restore (halaman lain yang hanya memiliki#bt_filtertetap berperilaku sama seperti sebelumnya).const identitasOpenkab = $(`meta[name="${AJAX_PARAMS_CONFIG.metaTagName}"]`).attr('content') || ''; let isAutoLoad = false; + let urlFilterRestoring = false; + const queryKodeKabupaten = new URLSearchParams(window.location.search).get('filter[kode_kabupaten]'); + const queryKodeKecamatan = new URLSearchParams(window.location.search).get('filter[kode_kecamatan]'); + const queryKodeDesa = new URLSearchParams(window.location.search).get('filter[kode_desa]');if (data[i].kode_kabupaten === filterValue) { isAutoLoad = true; + urlFilterRestoring = true; $("#filter_kabupaten").val(filterValue).trigger('change'); }$('#filter_kecamatan').prop('disabled', false); + if (urlFilterRestoring && queryKodeKecamatan) { + $('#filter_kecamatan').val(queryKodeKecamatan); + if ($('#filter_kecamatan').val() === queryKodeKecamatan) { + $('#filter_kecamatan').trigger('change'); + } else { + urlFilterRestoring = false; + } + } else { + urlFilterRestoring = false; + } if (isAutoLoad) { - $('#bt_filter').trigger('click'); + $('#bt_filter, #filter').trigger('click'); isAutoLoad = false; }$('#filter_desa').prop('disabled', false); + if (urlFilterRestoring && queryKodeDesa) { + $('#filter_desa').val(queryKodeDesa); + $('#filter_desa').trigger('change'); + } + urlFilterRestoring = false;5.
tests/Feature/DesaControllerTest.phpTest — Penambahan feature test untuk halaman Desa:
it_returns_200_on_desa_index()— memastikan halaman/desadapat diakses dan merender viewdesa.index.it_normalizes_null_string_filter_values()— memastikan nilai filter"null"dari query string dinormalisasi menjadinullpada controller.it_does_not_render_option_with_null_string_value()— memastikan view tidak merender<option value="null">dan tetap menampilkan opsi kabupaten dari URL.✅ Test Cases yang Diimplementasikan
/desayang hanya berisi parameter filter terisi (tidak lagifilter[kode_desa]=null)./desadenganfilter[kode_kabupaten]=5102→ tabel menampilkan seluruh desa pada kabupaten tersebut./desadenganfilter[kode_kecamatan]dan/ataufilter[kode_desa]→ select filter ter-restore dari URL dan tabel menampilkan data yang sesuai.sort=nama_desa(bukansort=undefined) sehingga API membalas200, bukan400.DesaControllerTestdanDasborControllerTestlulus (6 passed, 13 assertions).📸 Cara Menjalankan Uji Coba Manual
/dasbor), lalu pilih kabupaten (dan opsional kecamatan/desa) pada filter wilayah.?filter[kode_kabupaten]=5102&filter[nama_kabupaten]=TABANAN./desa, periksa tabel Data Desa:🤖 Cara Menjalankan Uji Coba Otomatis (Automated Test)
📸 Screenshot atau Video
openkabtest.mp4