Newer
Older
tracker-web-ui / src / main / resources / templates / track.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Device Tracking - <span th:text="${deviceGuid}"></span></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
    <style>
        #map { height: 500px; border: 2px solid #007bff; border-radius: 5px; }
        .info-panel { background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
    </style>
</head>
<body>
<div class="container mt-4">
    <h1>Tracking Device: <span th:text="${deviceGuid}"></span></h1>

    <div class="info-panel">
        <p><strong>Time Range:</strong>
            <span th:text="${#temporals.format(start, 'yyyy-MM-dd HH:mm')}"></span> -
            <span th:text="${#temporals.format(end, 'yyyy-MM-dd HH:mm')}"></span>
        </p>
        <p><strong>Locations found:</strong> <span th:text="${locations.size()}"></span></p>
        <a th:href="@{/}" class="btn btn-secondary">Back to device selection</a>
    </div>

    <div th:if="${error}" class="alert alert-danger" role="alert">
        <span th:text="${error}"></span>
    </div>

    <div id="map"></div>

    <div th:if="${not locations.empty}">
        <h3 class="mt-4">Location History</h3>
        <div class="table-responsive">
            <table class="table table-striped table-hover">
                <thead class="table-dark">
                <tr>
                    <th>Timestamp</th>
                    <th>Latitude</th>
                    <th>Longitude</th>
                </tr>
                </thead>
                <tbody>
                <tr th:each="location : ${locations}">
                    <td th:text="${#temporals.format(location.timestamp, 'yyyy-MM-dd HH:mm:ss')}"></td>
                    <td th:text="${location.latitude}"></td>
                    <td th:text="${location.longitude}"></td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

<script th:inline="javascript">
    /*<![CDATA[*/
    // Получаем данные напрямую из Thymeleaf
    var locationsData = /*[[${locations}]]*/ [];

    // Initialize map
    var map = L.map('map').setView([51.505, -0.09], 13);

    // Add OpenStreetMap tiles
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    console.log('Locations data:', locationsData);

    if (locationsData && locationsData.length > 0) {
        // Create array of coordinates
        var latlngs = locationsData.map(function(loc) {
            return [loc.latitude, loc.longitude];
        });

        // Create polyline with bright color
        var polyline = L.polyline(latlngs, {
            color: 'red',
            weight: 6,
            opacity: 0.8,
            lineJoin: 'round'
        }).addTo(map);

        // Add start marker (green icon)
        var startIcon = L.icon({
            iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
            shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
            iconSize: [25, 41],
            iconAnchor: [12, 41],
            popupAnchor: [1, -34],
            shadowSize: [41, 41]
        });

        var startMarker = L.marker(latlngs[0], {icon: startIcon}).addTo(map)
            .bindPopup('<strong>START</strong><br>Lat: ' + locationsData[0].latitude.toFixed(6) +
                      '<br>Lng: ' + locationsData[0].longitude.toFixed(6));

        // Add end marker (red icon)
        var endIcon = L.icon({
            iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
            shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
            iconSize: [25, 41],
            iconAnchor: [12, 41],
            popupAnchor: [1, -34],
            shadowSize: [41, 41]
        });

        var endMarker = L.marker(latlngs[latlngs.length-1], {icon: endIcon}).addTo(map)
            .bindPopup('<strong>END</strong><br>Lat: ' + locationsData[locationsData.length-1].latitude.toFixed(6) +
                      '<br>Lng: ' + locationsData[locationsData.length-1].longitude.toFixed(6));

        // Add intermediate markers for longer routes
        if (locationsData.length > 10) {
            for (var i = 1; i < locationsData.length - 1; i += Math.floor(locationsData.length / 5)) {
                L.marker([locationsData[i].latitude, locationsData[i].longitude]).addTo(map)
                    .bindPopup('Point ' + (i+1) + '<br>Lat: ' + locationsData[i].latitude.toFixed(6) +
                              '<br>Lng: ' + locationsData[i].longitude.toFixed(6));
            }
        }

        // Fit map to show the entire route with padding
        map.fitBounds(polyline.getBounds(), { padding: [50, 50] });

        // Add zoom control
        L.control.zoom({ position: 'topright' }).addTo(map);

    } else {
        // Show message if no data
        var messageDiv = document.createElement('div');
        messageDiv.className = 'alert alert-warning';
        messageDiv.innerHTML = 'No location data available for mapping.';
        messageDiv.style.margin = '20px';
        messageDiv.style.padding = '10px';
        messageDiv.style.textAlign = 'center';
        document.getElementById('map').appendChild(messageDiv);
    }
    /*]]>*/
</script>
</body>
</html>