update
This commit is contained in:
@ -11,6 +11,12 @@
|
|||||||
@section('customcss')
|
@section('customcss')
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
|
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
|
||||||
|
<style>
|
||||||
|
.geo-pending {
|
||||||
|
color: #999;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
@ -346,33 +352,59 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Isi row.startLoc / row.finishLoc yang masih kosong (null/undefined/'')
|
// Bikin id unik untuk elemen placeholder lokasi per baris+kolom,
|
||||||
// menggunakan hasil reverse geocode dari koordinat start_lat_long / finish_lat_long.
|
// dipakai untuk update teks langsung via DOM setelah geocode selesai di background.
|
||||||
// Nilai disimpan dalam bentuk encodeURIComponent supaya konsisten dengan
|
function geoElementId(row, kind) {
|
||||||
// field startLoc/finishLoc bawaan API yang memang sudah URL-encoded,
|
// kind: 'start' | 'finish'
|
||||||
// karena proses render memanggil decodeURIComponent(row.startLoc).
|
return `geo-${kind}-${row.id}-${row.trip_id}`;
|
||||||
async function fillMissingLocations(rows) {
|
}
|
||||||
|
|
||||||
|
// Jalankan reverse geocode di BACKGROUND (tidak menunggu / tidak blocking render tabel).
|
||||||
|
// Tabel sudah tampil duluan dengan placeholder "Load for location...", lalu begitu
|
||||||
|
// Nominatim balas untuk satu titik, teks placeholder-nya langsung di-update di tempat
|
||||||
|
// (tanpa redraw seluruh tabel), row demi row sesuai antrian reverseGeocode.
|
||||||
|
function scheduleBackgroundGeocode(rows) {
|
||||||
if (!Array.isArray(rows)) return;
|
if (!Array.isArray(rows)) return;
|
||||||
|
|
||||||
for (const row of rows) {
|
rows.forEach(row => {
|
||||||
if (!row.startLoc) {
|
const {
|
||||||
const {
|
lat: startLat,
|
||||||
lat,
|
lng: startLng
|
||||||
lng
|
} = parseLatLong(row.start_lat_long);
|
||||||
} = parseLatLong(row.start_lat_long);
|
const startNearestSite = findNearestSite(startLat, startLng);
|
||||||
const address = await reverseGeocode(lat, lng);
|
|
||||||
row.startLoc = address ? encodeURIComponent(address) : null;
|
// hanya perlu geocode kalau bukan site terdaftar & startLoc memang kosong
|
||||||
|
if (!startNearestSite && !row.startLoc) {
|
||||||
|
geocodeAndUpdateCell(geoElementId(row, 'start'), startLat, startLng);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!row.finishLoc) {
|
const {
|
||||||
const {
|
lat: finishLat,
|
||||||
lat,
|
lng: finishLng
|
||||||
lng
|
} = parseLatLong(row.finish_lat_long);
|
||||||
} = parseLatLong(row.finish_lat_long);
|
const finishNearestSite = findNearestSite(finishLat, finishLng);
|
||||||
const address = await reverseGeocode(lat, lng);
|
|
||||||
row.finishLoc = address ? encodeURIComponent(address) : null;
|
if (!finishNearestSite && !row.finishLoc) {
|
||||||
|
geocodeAndUpdateCell(geoElementId(row, 'finish'), finishLat, finishLng);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panggil reverseGeocode (sudah antri otomatis max 1 request/detik),
|
||||||
|
// begitu hasilnya datang, cari elemen placeholder di DOM lewat id-nya
|
||||||
|
// dan replace teksnya. Kalau elemen sudah tidak ada (misal tabel sudah
|
||||||
|
// di-reload/filter berubah), update di-skip secara aman.
|
||||||
|
function geocodeAndUpdateCell(elId, lat, lng) {
|
||||||
|
reverseGeocode(lat, lng).then(address => {
|
||||||
|
const $el = $('#' + elId);
|
||||||
|
if (!$el.length) return; // tabel sudah berganti, abaikan hasil basi ini
|
||||||
|
|
||||||
|
if (address) {
|
||||||
|
$el.text(Helper.shortenText(address, 255)).removeClass('geo-pending');
|
||||||
|
} else {
|
||||||
|
$el.text('-').removeClass('geo-pending');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================
|
// ================================
|
||||||
@ -421,17 +453,22 @@
|
|||||||
&poolcode=${$('#poolcode').val() || ''}
|
&poolcode=${$('#poolcode').val() || ''}
|
||||||
`,
|
`,
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
success: async function(json) {
|
success: function(json) {
|
||||||
// Isi startLoc/finishLoc yang kosong via Nominatim
|
// Tampilkan tabel DULUAN dengan semua data apa adanya
|
||||||
// SEBELUM tabel dirender, karena render() DataTables bersifat sinkron
|
// (baris yang startLoc/finishLoc kosong akan muncul
|
||||||
// dan tidak bisa menunggu fetch() di dalamnya.
|
// sebagai placeholder "Load for location...").
|
||||||
try {
|
|
||||||
await fillMissingLocations(json && json.data);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Gagal melengkapi lokasi via reverse geocode:', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(json);
|
callback(json);
|
||||||
|
|
||||||
|
// Reset antrian geocode supaya request dari load sebelumnya
|
||||||
|
// (misal filter lama) tidak numpuk / membuang kuota Nominatim.
|
||||||
|
geocodeQueue = Promise.resolve();
|
||||||
|
|
||||||
|
// Baru SETELAH itu, isi lokasi yang kosong di background.
|
||||||
|
// setTimeout 0 supaya DOM tabel sudah pasti ter-render dulu
|
||||||
|
// sebelum kita cari elemen placeholder-nya.
|
||||||
|
setTimeout(() => {
|
||||||
|
scheduleBackgroundGeocode(json && json.data);
|
||||||
|
}, 0);
|
||||||
},
|
},
|
||||||
error: function(xhr, status, error) {
|
error: function(xhr, status, error) {
|
||||||
if (status !== 'abort') {
|
if (status !== 'abort') {
|
||||||
@ -508,12 +545,23 @@
|
|||||||
} = parseLatLong(row.start_lat_long);
|
} = parseLatLong(row.start_lat_long);
|
||||||
const nearestSite = findNearestSite(startLat, startLng);
|
const nearestSite = findNearestSite(startLat, startLng);
|
||||||
|
|
||||||
// Prioritas: site terdaftar > startLoc (dari API atau hasil reverse geocode) > '-'
|
let locationLabel;
|
||||||
const locationLabel = nearestSite ?
|
if (nearestSite) {
|
||||||
formatSiteLabel(nearestSite) :
|
// Prioritas 1: site terdaftar
|
||||||
(row.startLoc ?
|
locationLabel = formatSiteLabel(nearestSite);
|
||||||
Helper.shortenText(decodeURIComponent(row.startLoc), 255) :
|
} else if (row.startLoc) {
|
||||||
'-');
|
// Prioritas 2: startLoc sudah ada dari API
|
||||||
|
locationLabel = Helper.shortenText(decodeURIComponent(row.startLoc), 255);
|
||||||
|
} else if (type === 'export') {
|
||||||
|
// Export bersifat sinkron, tidak bisa menunggu hasil geocode background
|
||||||
|
locationLabel = '-';
|
||||||
|
} else {
|
||||||
|
// Prioritas 3: kosong -> tampilkan placeholder dulu,
|
||||||
|
// nanti di-update otomatis oleh scheduleBackgroundGeocode()
|
||||||
|
// begitu hasil dari Nominatim datang.
|
||||||
|
locationLabel =
|
||||||
|
`<span id="${geoElementId(row, 'start')}" class="geo-pending">Load for location...</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'export') return locationLabel;
|
if (type === 'export') return locationLabel;
|
||||||
|
|
||||||
@ -529,11 +577,17 @@
|
|||||||
} = parseLatLong(row.finish_lat_long);
|
} = parseLatLong(row.finish_lat_long);
|
||||||
const nearestSite = findNearestSite(finishLat, finishLng);
|
const nearestSite = findNearestSite(finishLat, finishLng);
|
||||||
|
|
||||||
const locationLabel = nearestSite ?
|
let locationLabel;
|
||||||
formatSiteLabel(nearestSite) :
|
if (nearestSite) {
|
||||||
(row.finishLoc ?
|
locationLabel = formatSiteLabel(nearestSite);
|
||||||
Helper.shortenText(decodeURIComponent(row.finishLoc), 255) :
|
} else if (row.finishLoc) {
|
||||||
'-');
|
locationLabel = Helper.shortenText(decodeURIComponent(row.finishLoc), 255);
|
||||||
|
} else if (type === 'export') {
|
||||||
|
locationLabel = '-';
|
||||||
|
} else {
|
||||||
|
locationLabel =
|
||||||
|
`<span id="${geoElementId(row, 'finish')}" class="geo-pending">Load for location...</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'export') return locationLabel;
|
if (type === 'export') return locationLabel;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user