|
|
@@ -1,3 +1,12 @@
|
|
|
+const TRACK_TYPE_EMOJI = {
|
|
|
+ hiking: '🥾',
|
|
|
+ running: '🏃',
|
|
|
+ cycling: '🚴',
|
|
|
+ driving: '🚗',
|
|
|
+ train: '🚆',
|
|
|
+ other: '📍',
|
|
|
+};
|
|
|
+
|
|
|
const Browser = (() => {
|
|
|
let selectedDirId = null; // used as upload context
|
|
|
let expandedDirs = new Set();
|
|
|
@@ -145,14 +154,16 @@ const Browser = (() => {
|
|
|
for (const track of tracks) {
|
|
|
const dist = track.totalDistance ? formatDistance(track.totalDistance) : '';
|
|
|
const isSel = selectedTrackIds.has(track.id);
|
|
|
+ const typeEmoji = TRACK_TYPE_EMOJI[track.trackType] || '🗺️';
|
|
|
html += `<div class="tree-item track-item${isSel ? ' multi-selected' : ''}" data-id="${track.id}" draggable="true"
|
|
|
data-name="${escAttr(track.name)}" style="padding-left:${28 + baseIndent}px">
|
|
|
- <span class="item-icon">🗺️</span>
|
|
|
+ <span class="item-icon" title="${escAttr(track.trackType || '')}">${typeEmoji}</span>
|
|
|
<span class="item-name">${escHtml(track.name)}</span>
|
|
|
<span class="item-meta">${dist}</span>
|
|
|
<span class="item-date">${formatDate(track.trackDate || track.uploadDate)}</span>
|
|
|
<span class="item-actions">
|
|
|
<button class="item-btn view-track-btn" data-id="${track.id}" title="View on map">👁️</button>
|
|
|
+ <button class="item-btn edit-track-btn" data-id="${track.id}" data-name="${escAttr(track.name)}" data-type="${escAttr(track.trackType || '')}" title="Edit">✏️</button>
|
|
|
<button class="item-btn share-track-btn" data-id="${track.id}" title="Share">🔗</button>
|
|
|
<button class="item-btn move-track-btn" data-id="${track.id}" data-name="${escAttr(track.name)}" title="Move">📂</button>
|
|
|
<button class="item-btn delete-track-btn" data-id="${track.id}" data-name="${escAttr(track.name)}" title="Delete">🗑️</button>
|
|
|
@@ -243,6 +254,13 @@ const Browser = (() => {
|
|
|
btn.addEventListener('click', (e) => { e.stopPropagation(); shareTrack(parseInt(btn.dataset.id)); });
|
|
|
});
|
|
|
|
|
|
+ container.querySelectorAll('.edit-track-btn').forEach(btn => {
|
|
|
+ btn.addEventListener('click', (e) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ editTrack(parseInt(btn.dataset.id), btn.dataset.name, btn.dataset.type);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
container.querySelectorAll('.move-track-btn').forEach(btn => {
|
|
|
btn.addEventListener('click', (e) => {
|
|
|
e.stopPropagation();
|
|
|
@@ -493,17 +511,43 @@ const Browser = (() => {
|
|
|
|
|
|
function showTrackInfo(meta) {
|
|
|
if (!meta) return;
|
|
|
+ const typeEmoji = TRACK_TYPE_EMOJI[meta.trackType] || null;
|
|
|
+ const typeLabel = meta.trackType
|
|
|
+ ? `${typeEmoji ? typeEmoji + ' ' : ''}${meta.trackType.charAt(0).toUpperCase() + meta.trackType.slice(1)}`
|
|
|
+ : null;
|
|
|
const panel = document.getElementById('track-info-panel');
|
|
|
document.getElementById('track-info-content').innerHTML = `
|
|
|
<h3>${escHtml(meta.name || 'Track')}</h3>
|
|
|
<div class="info-row"><label>Distance</label><span>${formatDistance(meta.totalDistance)}</span></div>
|
|
|
<div class="info-row"><label>Points</label><span>${meta.pointCount || 0}</span></div>
|
|
|
${meta.trackDate ? `<div class="info-row"><label>Date</label><span>${formatDate(meta.trackDate)}</span></div>` : ''}
|
|
|
+ ${typeLabel ? `<div class="info-row"><label>Type</label><span>${escHtml(typeLabel)}</span></div>` : ''}
|
|
|
`;
|
|
|
panel.style.display = 'block';
|
|
|
document.getElementById('track-info-close').onclick = () => { panel.style.display = 'none'; };
|
|
|
}
|
|
|
|
|
|
+ function editTrack(trackId, currentName, currentType) {
|
|
|
+ const modal = document.getElementById('edit-track-modal');
|
|
|
+ document.getElementById('edit-track-name').value = currentName || '';
|
|
|
+ document.getElementById('edit-track-type').value = currentType || '';
|
|
|
+ modal.style.display = 'flex';
|
|
|
+
|
|
|
+ document.getElementById('edit-track-save-btn').onclick = async () => {
|
|
|
+ const name = document.getElementById('edit-track-name').value.trim();
|
|
|
+ const trackType = document.getElementById('edit-track-type').value || null;
|
|
|
+ if (!name) { showToast('Name cannot be empty', 'error'); return; }
|
|
|
+ modal.style.display = 'none';
|
|
|
+ try {
|
|
|
+ await API.updateTrack(trackId, { name, trackType });
|
|
|
+ await reload();
|
|
|
+ showToast('Track updated', 'success');
|
|
|
+ } catch (e) {
|
|
|
+ showToast('Error: ' + e.message, 'error');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
async function deleteTrack(id) {
|
|
|
try {
|
|
|
MapView.removeTrack(id);
|