Fleet Manager
Co-Authored-By: mike8643 <98910897+mike8643@users.noreply.github.com>
This commit is contained in:
18
selfdrive/frogpilot/fleetmanager/templates/about.html
Normal file
18
selfdrive/frogpilot/fleetmanager/templates/about.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
About
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>About</h1>
|
||||
<br>
|
||||
<footer class="small text-center text-muted" style="word-wrap: break-word;">
|
||||
Special thanks to:<br><br>
|
||||
ntegan1<br>
|
||||
royjr<br>
|
||||
AlexandreSato<br>
|
||||
actuallylemoncurd
|
||||
</footer>
|
||||
{% endblock %}
|
||||
11
selfdrive/frogpilot/fleetmanager/templates/addr.html
Normal file
11
selfdrive/frogpilot/fleetmanager/templates/addr.html
Normal file
@@ -0,0 +1,11 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
FrogPilot Navigation
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% with gmap_key=gmap_key, lon=lon, lat=lat %}
|
||||
{% include "addr_input.html" %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
62
selfdrive/frogpilot/fleetmanager/templates/addr_input.html
Normal file
62
selfdrive/frogpilot/fleetmanager/templates/addr_input.html
Normal file
@@ -0,0 +1,62 @@
|
||||
{% block main %}
|
||||
<!-- Your form markup -->
|
||||
<form name="searchForm" method="post">
|
||||
<fieldset class="uk-fieldset">
|
||||
<div class="uk-margin">
|
||||
<select class="uk-select" name="fav_val">
|
||||
<option value="favorites">Select Saved Destinations</option>
|
||||
<option value="home">Home</option>
|
||||
<option value="work">Work</option>
|
||||
<option value="fav1">Favorite 1</option>
|
||||
<option value="fav2">Favorite 2</option>
|
||||
<option value="fav3">Favorite 3</option>
|
||||
</select>
|
||||
<input class="uk-input" type="text" name="addr_val" id="pac-input" placeholder="Search a place">
|
||||
<input class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit" value="Search">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<!-- Include the Google Maps Places API script conditionally with JavaScript -->
|
||||
<script>
|
||||
// attach gmap_key to variable
|
||||
let gmap = "{{gmap_key}}";
|
||||
|
||||
// Check if gmap_key is defined
|
||||
if (gmap && gmap !== "None") {
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://maps.googleapis.com/maps/api/js?key={{gmap_key}}&libraries=places&callback=initAutocomplete';
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
document.head.appendChild(script);
|
||||
|
||||
// Define the callback function for place_changed
|
||||
function onPlaceChanged() {
|
||||
var place = autocomplete.getPlace();
|
||||
|
||||
// Check if the place has a formatted address
|
||||
if (place.formatted_address) {
|
||||
// Set the value of the input field to the formatted address
|
||||
document.getElementById('pac-input').value = place.formatted_address;
|
||||
}
|
||||
}
|
||||
|
||||
// Define the autocomplete variable
|
||||
var autocomplete;
|
||||
|
||||
// Define the initAutocomplete function with initial bounds
|
||||
function initAutocomplete() {
|
||||
var center = new google.maps.LatLng({{lat}}, {{lon}});
|
||||
var bounds = new google.maps.Circle({ center: center, radius: 5000 }).getBounds();
|
||||
|
||||
autocomplete = new google.maps.places.Autocomplete(
|
||||
document.getElementById('pac-input'),
|
||||
{
|
||||
bounds: bounds // Set initial bounds here
|
||||
}
|
||||
);
|
||||
|
||||
autocomplete.addListener('place_changed', onPlaceChanged);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
addr_input
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form name="setSkTokenForm" method="post">
|
||||
<fieldset class="uk-fieldset">
|
||||
<legend class="uk-legend">Set your Mapbox <b>Secret Token</b></legend>
|
||||
<div style="padding: 5px; color: red; font-weight: bold;">{{msg}}</div>
|
||||
<div class="uk-margin">
|
||||
<input class="uk-input" type="text" name="sk_token_val" placeholder="sk.xxxxxxx...">
|
||||
<input class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit" value="Set">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
11
selfdrive/frogpilot/fleetmanager/templates/error.html
Normal file
11
selfdrive/frogpilot/fleetmanager/templates/error.html
Normal file
@@ -0,0 +1,11 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
About
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br> Oops
|
||||
<br><br><br><br>
|
||||
{{ error | safe }}
|
||||
{% endblock %}
|
||||
16
selfdrive/frogpilot/fleetmanager/templates/error_log.html
Normal file
16
selfdrive/frogpilot/fleetmanager/templates/error_log.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Error Log
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Error Log of<br>{{ file_name }}</h1>
|
||||
<br>
|
||||
{% endblock %}
|
||||
|
||||
{% block unformated %}
|
||||
<pre style="font-size: x-small; margin: 20px;">{{ file_content }}</pre>
|
||||
<br><br>
|
||||
{% endblock %}
|
||||
14
selfdrive/frogpilot/fleetmanager/templates/error_logs.html
Normal file
14
selfdrive/frogpilot/fleetmanager/templates/error_logs.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Error Logs
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Error Logs</h1>
|
||||
<br>
|
||||
{% for row in rows %}
|
||||
<a href="/error_logs/{{ row }}">{{ row }}</a><br>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
15
selfdrive/frogpilot/fleetmanager/templates/footage.html
Normal file
15
selfdrive/frogpilot/fleetmanager/templates/footage.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Dashcam Routes
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Dashcam Routes</h1>
|
||||
<br>
|
||||
{% for row in rows %}
|
||||
<a href="/footage/{{ row }}">{{ row }}</a><br>
|
||||
{% endfor %}
|
||||
<br><br>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
addr_input
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form name="setGmapTokenForm" method="post">
|
||||
<fieldset class="uk-fieldset">
|
||||
<legend class="uk-legend">Set your Google Map API Key</legend>
|
||||
<div class="uk-margin">
|
||||
<input class="uk-input" type="text" name="gmap_key_val" placeholder="Google Map API KEY">
|
||||
<input class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit" value="Submit">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
14
selfdrive/frogpilot/fleetmanager/templates/index.html
Normal file
14
selfdrive/frogpilot/fleetmanager/templates/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Home
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Fleet Manager</h1>
|
||||
<br>
|
||||
<a href='/footage'>View Dashcam Footage</a><br>
|
||||
<br><a href='/screenrecords'>View Screen Recordings</a><br>
|
||||
<br><a href='/error_logs'>Access Error Logs</a><br>
|
||||
{% endblock %}
|
||||
100
selfdrive/frogpilot/fleetmanager/templates/layout.html
Normal file
100
selfdrive/frogpilot/fleetmanager/templates/layout.html
Normal file
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" id="htmlElement">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1, width=device-width">
|
||||
<link href="/static/favicon.ico" rel="icon">
|
||||
<!-- http://getbootstrap.com/docs/5.3/ -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
|
||||
<style>
|
||||
.navbar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.navbar-brand img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
<!-- UIkit CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/css/uikit.min.css" />
|
||||
|
||||
<!-- UIkit JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit-icons.min.js"></script>
|
||||
|
||||
<style>
|
||||
/* Dark mode styles */
|
||||
#htmlElement.dark-mode,
|
||||
#htmlElement.dark-mode input,
|
||||
#htmlElement.dark-mode select,
|
||||
#htmlElement.dark-mode body,
|
||||
#htmlElement.dark-mode h1 {
|
||||
background-color: #121212; /* Dark background color */
|
||||
color: #ffffff; /* Light text color */
|
||||
}
|
||||
.nav-link {
|
||||
display: inline-block;
|
||||
padding: 0 15px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<title>FrogPilot: {% block title %}{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-fixed-top navbar-expand-sm navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a href="/" class="navbar-brand mb-0 h1">
|
||||
<img class="d-inline-block align-top mr-2" src="/static/frog.png" /> FrogPilot </a>
|
||||
<button type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" class="navbar-toggler" aria-controls="navbarNav" aria-expanded="false" arial-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse ml-auto" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a href="/footage" class="nav-link">Dashcam Routes</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a href="/screenrecords" class="nav-link">Screen Recordings</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a href="/error_logs" class="nav-link">Error Logs</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a href="/addr_input" class="nav-link">Navigation</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container-fluid p-7 text-center"> {% block main %}{% endblock %} </main>
|
||||
{% block unformated %}{% endblock %}
|
||||
|
||||
<button class="uk-button uk-button-default uk-margin-small-right" onclick="toggleDarkMode()">Toggle Dark Mode</button>
|
||||
|
||||
<script>
|
||||
function setCookie(name, value, days) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
document.cookie = `${name}=${value};expires=${date.toUTCString()};path=/`;
|
||||
}
|
||||
function getCookie(name) {
|
||||
return document.cookie.split('; ')
|
||||
.find(row => row.startsWith(name))
|
||||
?.split('=')[1] || null;
|
||||
}
|
||||
function toggleDarkMode() {
|
||||
console.log('Toggle Dark Mode function called');
|
||||
const htmlElement = document.documentElement;
|
||||
htmlElement.classList.toggle('dark-mode');
|
||||
setCookie('darkMode', htmlElement.classList.contains('dark-mode'), 365);
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const htmlElement = document.documentElement;
|
||||
htmlElement.classList.toggle('dark-mode', getCookie('darkMode') === 'true');
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
addr_input
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div><img src="https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-l+000({{lon}},{{lat}})/{{lon}},{{lat}},14/300x300?access_token={{token}}" /></div>
|
||||
<div style="padding: 5px; font-size: 10px;">{{addr}}</div>
|
||||
<form name="navForm" method="post">
|
||||
<fieldset class="uk-fieldset">
|
||||
<div class="uk-margin">
|
||||
<input type="hidden" name="name" value="{{addr}}">
|
||||
<input type="hidden" name="lat" value="{{lat}}">
|
||||
<input type="hidden" name="lon" value="{{lon}}">
|
||||
<select id="save_type" name="save_type" class="uk-select">
|
||||
<option value="recent">Recent</option>
|
||||
<option value="home">Set Home</option>
|
||||
<option value="work">Set Work</option>
|
||||
<option value="fav1">Set Favorite 1</option>
|
||||
<option value="fav2">Set Favorite 2</option>
|
||||
<option value="fav3">Set Favorite 3</option>
|
||||
</select>
|
||||
<input class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit" value="Start Navigation">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
149
selfdrive/frogpilot/fleetmanager/templates/nav_directions.html
Normal file
149
selfdrive/frogpilot/fleetmanager/templates/nav_directions.html
Normal file
@@ -0,0 +1,149 @@
|
||||
{% block main %}
|
||||
<div id="destinationHeading" style="font-weight: bold;"></div>
|
||||
<div id="jsonOutput" style="text-align: left;"></div>
|
||||
<style>
|
||||
/* Added CSS styles to display images and text on the same line */
|
||||
#jsonOutput span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#jsonOutput img {
|
||||
margin-right: 10px; /* Adjust the margin as needed */
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
let useMetricUnits = false;
|
||||
let previousNavdirectionsUuid = null;
|
||||
let previousCurrentStepUuid = null;
|
||||
let jsonData = null;
|
||||
let initNav = 0;
|
||||
|
||||
async function loadCurrentStep() {
|
||||
try {
|
||||
const response = await fetch('CurrentStep.json'); // Load CurrentStep.json
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch CurrentStep.json.');
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
return json;
|
||||
} catch (error) {
|
||||
console.error('Error fetching or parsing CurrentStep.json:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNavdirectionsData() {
|
||||
try {
|
||||
const response = await fetch('navdirections.json'); // Load navdirections.json
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch JSON file. Status: ${response.status}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
// Check if the UUIDs match
|
||||
const match = json.uuid === previousCurrentStepUuid;
|
||||
|
||||
previousNavdirectionsUuid = json.uuid;
|
||||
jsonData = json;
|
||||
initNav = 1;
|
||||
return jsonData;
|
||||
} catch (error) {
|
||||
console.error('Error fetching or parsing JSON data:', error);
|
||||
return jsonData; // Return the existing data on error
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchAndDisplayData() {
|
||||
const currentStepData = await loadCurrentStep();
|
||||
|
||||
if (currentStepData !== null) {
|
||||
// Set the initial value for `currentStep` based on `CurrentStep.json`
|
||||
previousCurrentStepUuid = currentStepData.uuid;
|
||||
}
|
||||
|
||||
if (currentStepData.uuid != previousNavdirectionsUuid) {
|
||||
await loadNavdirectionsData();
|
||||
}
|
||||
|
||||
if (initNav === 0) {
|
||||
await loadNavdirectionsData();
|
||||
}
|
||||
|
||||
// Check if jsonData is available and proceed
|
||||
if (jsonData) {
|
||||
// Access the data you need from the loaded JSON
|
||||
const firstRoute = jsonData.routes[0];
|
||||
const firstLeg = firstRoute.legs[0];
|
||||
const steps = firstLeg.steps;
|
||||
const destination = firstRoute.Destination;
|
||||
|
||||
// Determine whether to use metric or imperial units based on the 'Metric' key
|
||||
useMetricUnits = firstRoute.Metric === true; // Removed `const` to update the global useMetricUnits
|
||||
|
||||
// Display the 'destination' value on the webpage
|
||||
const destinationHeading = document.getElementById('destinationHeading');
|
||||
destinationHeading.textContent = `Destination: ${destination}`;
|
||||
|
||||
// Display values from the steps
|
||||
const jsonOutputDiv = document.getElementById('jsonOutput');
|
||||
jsonOutputDiv.innerHTML = '';
|
||||
|
||||
for (let i = currentStepData.CurrentStep; i < steps.length - 1; i++) {
|
||||
const step = steps[i];
|
||||
const instruction0 = steps[i].maneuver.instruction;
|
||||
const instruction = steps[i + 1].maneuver.instruction;
|
||||
const maneuverType = steps[i + 1].maneuver.type;
|
||||
const modifier = steps[i + 1].maneuver.modifier;
|
||||
let distance = step.distance;
|
||||
|
||||
if (!useMetricUnits) {
|
||||
// Convert distance to miles if using imperial units
|
||||
distance = distance * 0.000621371;
|
||||
} else {
|
||||
distance = distance / 1000; // Convert meters to kilometers
|
||||
}
|
||||
const sanitizedManeuverType = maneuverType.replace(/\s+/g, '_');
|
||||
const sanitizedModifier = modifier ? `_${modifier.replace(/\s+/g, '_')}` : '';
|
||||
const filterStyle = !htmlElement.classList.contains('dark-mode') ? 'filter: invert(100%);' : '';
|
||||
// Display the values on the webpage
|
||||
if (i === 0) {
|
||||
jsonOutputDiv.innerHTML += `
|
||||
<hr>
|
||||
<span>
|
||||
<img src="/navigation/direction_depart.png" alt="${maneuverType} icon" width="25" height="25" style="${filterStyle}">
|
||||
<p>${instruction0}</p>
|
||||
</span>
|
||||
<hr>
|
||||
`;
|
||||
}
|
||||
jsonOutputDiv.innerHTML += `
|
||||
<span>
|
||||
<img src="/navigation/direction_${sanitizedManeuverType}${sanitizedModifier}.png" alt="${maneuverType} icon" width="25" height="25" style="${filterStyle}">
|
||||
<p>In ${distance.toFixed(1)} ${useMetricUnits ? 'km' : 'miles'}: ${instruction}</p>
|
||||
</span>
|
||||
<hr>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load `CurrentStep.json` initially
|
||||
loadCurrentStep().then((currentStepData) => {
|
||||
if (currentStepData !== null) {
|
||||
// Set the initial value for `currentStep` based on `CurrentStep.json`
|
||||
previousCurrentStepUuid = currentStepData.uuid;
|
||||
loadNavdirectionsData();
|
||||
// Fetch and display data initially
|
||||
fetchAndDisplayData();
|
||||
}
|
||||
});
|
||||
|
||||
// Periodically fetch `CurrentStep.json` and display data every 5 seconds
|
||||
setInterval(fetchAndDisplayData, 5000); // Adjust the interval as needed (in milliseconds)
|
||||
</script>
|
||||
{% endblock %}
|
||||
13
selfdrive/frogpilot/fleetmanager/templates/nonprime.html
Normal file
13
selfdrive/frogpilot/fleetmanager/templates/nonprime.html
Normal file
@@ -0,0 +1,13 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
addr_input
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% with gmap_key=gmap_key, lon=lon, lat=lat %}
|
||||
{% include "addr_input.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% include "nav_directions.html" %}
|
||||
{% endblock %}
|
||||
9
selfdrive/frogpilot/fleetmanager/templates/prime.html
Normal file
9
selfdrive/frogpilot/fleetmanager/templates/prime.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
FrogPilot Navigation
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include "nav_directions.html" %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
addr_input
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form name="setPkTokenForm" method="post">
|
||||
<fieldset class="uk-fieldset">
|
||||
<legend class="uk-legend">Set your Mapbox <b>Public Token</b></legend>
|
||||
<div style="padding: 5px; color: red; font-weight: bold;">{{msg}}</div>
|
||||
<div class="uk-margin">
|
||||
<input class="uk-input" type="text" name="pk_token_val" placeholder="pk.xxxxxxx...">
|
||||
<input class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit" value="Set">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
57
selfdrive/frogpilot/fleetmanager/templates/route.html
Normal file
57
selfdrive/frogpilot/fleetmanager/templates/route.html
Normal file
@@ -0,0 +1,57 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Dashcam Segments
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
{% autoescape false %}
|
||||
<br>
|
||||
<h1>Dashcam Segments (one per minute)</h1>
|
||||
<br>
|
||||
<video id="video" width="320" height="240" controls autoplay="autoplay" style="background:black">
|
||||
</video>
|
||||
<br><br>
|
||||
current segment: <span id="currentsegment"></span>
|
||||
<br>
|
||||
current view: <span id="currentview"></span>
|
||||
<br>
|
||||
<a download="{{ route }}-{{ query_type }}.mp4" href="/footage/full/{{ query_type }}/{{ route }}">download full route {{ query_type }}</a>
|
||||
<br><br>
|
||||
<a href="{{ route }}?0,qcamera">qcamera</a> -
|
||||
<a href="{{ route }}?0,fcamera">fcamera</a> -
|
||||
<a href="{{ route }}?0,dcamera">dcamera</a> -
|
||||
<a href="{{ route }}?0,ecamera">ecamera</a>
|
||||
<br><br>
|
||||
{{ links }}
|
||||
<script>
|
||||
var video = document.getElementById('video');
|
||||
var tracks = {
|
||||
list: [{{ segments }}],
|
||||
index: {{ query_segment }},
|
||||
next: function() {
|
||||
if (this.index == this.list.length - 1) this.index = 0;
|
||||
else {
|
||||
this.index += 1;
|
||||
}
|
||||
},
|
||||
play: function() {
|
||||
return ( "{{ query_type }}/" + this.list[this.index] );
|
||||
}
|
||||
}
|
||||
video.addEventListener('ended', function(e) {
|
||||
tracks.next();
|
||||
video.src = tracks.play();
|
||||
document.getElementById("currentsegment").textContent=video.src.split("/")[5];
|
||||
document.getElementById("currentview").textContent=video.src.split("/")[4];
|
||||
video.load();
|
||||
video.play();
|
||||
});
|
||||
video.src = tracks.play();
|
||||
document.getElementById("currentsegment").textContent=video.src.split("/")[5];
|
||||
document.getElementById("currentview").textContent=video.src.split("/")[4];
|
||||
</script>
|
||||
{% endautoescape %}
|
||||
<br><br>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Screen Recordings
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Screen Recordings</h1>
|
||||
<br>
|
||||
<video id="video" width="320" height="240" controls autoplay="autoplay" style="background:black">
|
||||
</video>
|
||||
<br><br>
|
||||
current view: <span id="mycurrentview"></span>
|
||||
<br>
|
||||
<a href="/screenrecords/download/{{ clip }}">download: {{ clip }}</a><br><br>
|
||||
<script>
|
||||
var video = document.getElementById("video");
|
||||
var track = {
|
||||
play: function() {
|
||||
return ( "/screenrecords/play/pipe/" + '{{ clip }}' );
|
||||
}
|
||||
}
|
||||
video.src = track.play();
|
||||
document.getElementById("mycurrentview").textContent=video.src.split("/")[6];
|
||||
</script>
|
||||
{% for row in rows %}
|
||||
<a href="/screenrecords/{{ row }}">{{ row }}</a><br>
|
||||
{% endfor %}
|
||||
<br><br>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user