Support for location picker

This commit is contained in:
Matteo Gheza 2020-11-13 15:22:26 +01:00
parent 93dd68f0e8
commit 5e14d364ef
11 changed files with 286 additions and 20 deletions

View File

@ -474,6 +474,7 @@ INSERT INTO `".$prefix."_options` (`id`, `name`, `value`, `enabled`, `created_ti
INSERT INTO `".$prefix."_options` (`id`, `name`, `value`, `enabled`, `created_time`, `last_edit`, `user_id`) VALUES (NULL, 'service_remove', 1, 1, current_timestamp(), current_timestamp(), '1');
INSERT INTO `".$prefix."_options` (`id`, `name`, `value`, `enabled`, `created_time`, `last_edit`, `user_id`) VALUES (NULL, 'training_edit', 1, 1, current_timestamp(), current_timestamp(), '1');
INSERT INTO `".$prefix."_options` (`id`, `name`, `value`, `enabled`, `created_time`, `last_edit`, `user_id`) VALUES (NULL, 'training_remove', 1, 1, current_timestamp(), current_timestamp(), '1');
INSERT INTO `".$prefix."_options` (`id`, `name`, `value`, `enabled`, `created_time`, `last_edit`, `user_id`) VALUES (NULL, 'use_location_picker', 1, 1, current_timestamp(), current_timestamp(), '1');
$option_check_cf_ip");
mt_srand(10);
$prep->bindValue(':hidden', ($visible ? 0 : 1), PDO::PARAM_INT);

View File

@ -11,7 +11,7 @@ import '../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css'
import 'time-input-polyfill/auto';
import 'jquery-pjax';
$(document).pjax('a', '#content');
$(document).pjax('a', '#content', {timeout: 100000});
$(document).on('pjax:start', function() {
if(window.loadTable_interval !== undefined){
clearInterval(window.loadTable_interval);
@ -71,6 +71,7 @@ $( document ).ready(function() {
window.dispatchEvent(new Event("cookieAlertAccept"))
});
});
if (getCookie("authenticated")) {
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
@ -83,15 +84,29 @@ if (getCookie("authenticated")) {
}
}
function fillTable(data){
function fillTable(data, replaceLatLngWithMap=false){
$("#table_body").empty();
$.each(data, function(num, item) {
var row = document.createElement("tr");
$.each(item, function(num, i) {
$.each(data, function(row_num, item) {
let row = document.createElement("tr");
$.each(item, function(cell_num, i) {
if(i !== null){
var cell = document.createElement("td");
cell.innerHTML = i;
row.appendChild(cell);
if(replaceLatLngWithMap && i.match(/[+-]?\d+([.]\d+)?[;][+-]?\d+([.]\d+)?/gm)){
let lat = i.split(";")[0];
let lng = i.split(";")[1];
let mapDiv = document.createElement("div");
mapDiv.className = "map";
mapDiv.id = "map-"+row_num;
var mapScript = document.createElement("script");
mapScript.appendChild(document.createTextNode("load_map("+lat+", "+lng+", \"map-"+row_num+"\", false)"));
mapDiv.appendChild(mapScript);
let cell = document.createElement("td");
cell.appendChild(mapDiv);
row.appendChild(cell);
} else {
let cell = document.createElement("td");
cell.innerHTML = i;
row.appendChild(cell);
}
}
});
document.getElementById("table_body").appendChild(row);
@ -101,8 +116,9 @@ function fillTable(data){
var offline = false;
var loadTable_interval = undefined;
function loadTable(table_page, set_interval=true, interval=10000, onlineReload=false){
let replaceLatLngWithMap = table_page == "services" || table_page == "trainings";
$.getJSON( "resources/ajax/ajax_"+table_page+".php", function( data, status, xhr ) {
fillTable(data);
fillTable(data, replaceLatLngWithMap);
var headers = new Headers();
headers.append('date', Date.now());
caches.open('tables-1').then((cache) => {
@ -119,14 +135,14 @@ function loadTable(table_page, set_interval=true, interval=10000, onlineReload=f
}
}).fail(function(data, status) {
if(status == "parsererror"){
if($("#table_body").children().length == 0) {
loadTable(table_page, set_interval, interval);
if($("#table_body").children().length == 0) { //this is a server-side authentication error on some cheap hosting providers
loadTable(table_page, set_interval, interval); //retry
} // else nothing
} else {
caches.open('tables-1').then(cache => {
cache.match("/table_"+table_page+".json").then(response => {
response.json().then(data => {
fillTable(data);
fillTable(data, replaceLatLngWithMap);
console.log("Table loaded from cache");
$("#offline_update").text(new Date(parseInt(response.headers.get("date"))).toLocaleString());
});
@ -147,4 +163,6 @@ function loadTable(table_page, set_interval=true, interval=10000, onlineReload=f
window.loadTable_interval = loadTable_interval;
window.fillTable = fillTable;
window.loadTable = loadTable;
window.loadTable = loadTable;
window.setCookie = setCookie;
window.getCookie = getCookie;

View File

@ -0,0 +1,37 @@
div#map {
width: 100%;
height: 500px;
}
.map {
width: 100%;
height: 500px;
}
div#search {
background-color: rgba(255, 255, 255, 0.4);
bottom: 40px;
left: 40px;
width: auto;
height: auto;
padding: 10px;
}
div#results {
font-style: sans-serif;
color: black;
font-size: 75%;
}
.fa{
vertical-align: middle;
font-size: 25px;
}
.fa.fa-map-marker-alt,.fa.fa-spinner.fa-spin {
line-height: inherit;
}
.leaflet-pane.leaflet-shadow-pane {
display: none;
}

View File

@ -2,10 +2,200 @@ import L from 'leaflet';
import 'leaflet.locatecontrol';
import '../node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.css'
import '../node_modules/leaflet/dist/leaflet.css';
import './maps.css';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: 'resources/dist/marker-icon-2x.png',
iconUrl: 'resources/dist/marker-icon.png',
shadowUrl: 'resources/dist/marker-shadow.png',
});
});
var marker;
var map;
function set_marker(LatLng){
if(marker){
console.log("Marker exists");
//console.log(marker);
marker.remove();
}
console.log(LatLng);
if($("input[name='luogo']").val() !== undefined){
$("input[name='luogo']").val(LatLng.lat + ";" + LatLng.lng);
}
marker = L.marker(LatLng).addTo(map);
}
function load_map(lat=undefined, lng=undefined, selector_id=undefined, select=true) {
if(lat == undefined && lng == undefined){
lat = 45.5285; //TODO: replace hard-coded into cookie reading
lng = 10.2956;
}
if(selector_id == undefined){
selector_id = "map";
}
let zoom = select ? 10 : 17;
let latLng = new L.LatLng(lat, lng);
map = new L.Map(selector_id, {zoomControl: true});
let osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttribution = 'Map data &copy; 2012 <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
osm = new L.TileLayer(osmUrl, {maxZoom: 20, attribution: osmAttribution});
map.setView(latLng, zoom).addLayer(osm);
if(select){
map.on('click', function(e) {
set_marker(e.latlng);
});
L.Control.CustomLocate = L.Control.Locate.extend({
_drawMarker: function() {
set_marker(this._event.latlng);
},
_onDrag: function(){},
_onZoom: function(){},
_onZoomEnd: function(){},
});
let lc = new L.Control.CustomLocate({
icon: "fa fa-map-marker",
cacheLocation: false, //disabled for privacy reasons
}).addTo(map);
if($("#addr").val() !== undefined){
document.getElementById("addr").addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
document.querySelector("#search > button").click();
}
});
}
if(getCookie("experimental_read_clipboard")){
window.addEventListener("focus", function(event) {
if($("#addr").val() == ""){
console.log("Loading location from clipboard");
navigator.clipboard.readText().then(text => {
$("#addr").val(text);
if(!addr_search()){
$("#addr").val("");
}
}).catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
});
}
} else {
set_marker(latLng);
}
map.invalidateSize();
}
// from unknown source in the Internet
function chooseAddr(lat, lng, zoom=undefined, lat1=undefined, lng1=undefined, lat2=undefined, lng2=undefined, osm_type=undefined) {
let lat = lat.replace(",", ".");
let lng = lng.replace(",", ".");
if(lat1 !== undefined && lng1 !== undefined && lat2 !== undefined && lng2 !== undefined && osm_type !== undefined){
let loc1 = new L.LatLng(lat1, lng1);
let loc2 = new L.LatLng(lat2, lng2);
let bounds = new L.LatLngBounds(loc1, loc2);
console.log(lat1, lng1, lat2, lng2, osm_type);
set_marker(new L.LatLng(lat, lng));
if (feature) {
map.removeLayer(feature);
}
if (osm_type == "node") {
map.fitBounds(bounds);
map.setZoom(18);
} else {
let loc3 = new L.LatLng(lat1, lng2);
let loc4 = new L.LatLng(lat2, lng1);
feature = L.polyline( [loc1, loc4, loc2, loc3, loc1], {color: 'red'}).addTo(map);
map.fitBounds(bounds);
}
} else if (lat !== undefined && lng !== undefined){
let loc = new L.LatLng(lat, lng);
console.log(loc);
set_marker(loc);
if(zoom !== undefined){
map.setView(loc, zoom);
} else {
map.setView(loc);
}
}
}
// started from https://derickrethans.nl/leaflet-and-nominatim.html
function addr_search(string_results_found=undefined, string_results_not_found=undefined) {
function searchError(error, checkClipboard){
if(!checkClipboard){
$('<p>', { html: string_results_not_found }).appendTo('#results');
console.error(error);
}
return false;
}
let inp = document.getElementById("addr").value;
//if translation strings are not defined, skip the nominatim step and don't log errors (no console.error)
let checkClipboard = string_results_found==undefined && string_results_not_found==undefined;
$('#results').empty();
if(inp.match("\@(-?[\d\.]*)")){ //Google Maps
try {
inp = inp.split("@")[1].split(",");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.includes("#map=")) { //OpenStreetMap website
try {
inp = inp.split("#map=")[1].split("/");
chooseAddr(inp[1], inp[2], inp[0]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.match(/[0-9]+,\s[0-9]+/)) { //Bing
try {
inp = inp.split(", ");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(inp.match(/[0-9]+;[0-9]+/)) { //DB dump
try {
inp = inp.split(";");
chooseAddr(inp[0], inp[1]);
return true;
} catch (error) {
searchError(error, checkClipboard);
}
} else if(!checkClipboard) {
$.getJSON('https://nominatim.openstreetmap.org/search?format=json&limit=5&q=' + inp, function(data) {
let items = [];
$.each(data, function(key, val) {
items.push("<li><a href='' onclick='chooseAddr(\"" + val.lat + "\", \"" + val.lon + "\", undefined, " + val.boundingbox[0] + ", " + val.boundingbox[2] + ", " + val.boundingbox[1] + ", " + val.boundingbox[3] + ", \"" + val.osm_type + "\"); return false;'>" + val.display_name + '</a></li>');
});
if (items.length != 0) {
$('<p>', { html: string_results_found+":" }).appendTo('#results');
$('<ul/>', {
'class': 'results-list',
html: items.join('')
}).appendTo('#results');
} else {
$('<p>', { html: string_results_not_found }).appendTo('#results');
}
});
} else {
return false;
}
}
window.load_map = load_map;
window.addr_search = addr_search;
window.chooseAddr = chooseAddr;

View File

@ -24,7 +24,7 @@ function fetchHandler(event, content_type, not_found_message){
);
}
self.addEventListener('fetch', function (event) {
console.log(event.request);
//console.log(event.request);
var request = event.request;
// https://stackoverflow.com/a/49719964

View File

@ -328,7 +328,7 @@
xhr.send();
}
check();
//check();
/* setInterval(function() {
check();
}, 30000); */

View File

@ -128,8 +128,20 @@ textarea {
</div>
{% endfor %}
<br>
{% if option('use_location_picker') %}
<label><b>{{ 'Service place'|t }}</b></label>
<div id="map"></div>
<div id="search">
<input type="text" name="addr" value="" id="addr" size="10" />
<button type="button" onclick="addr_search('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');" class="btn btn-primary">{{ 'Search'|t }}</button>
<div id="results"></div>
</div>
<input type="hidden" name="luogo" value="" />
<script src="resources/dist/maps.js" onload="load_map();"></script>
{% else %}
<label><b>{{ 'Service place'|t }}</b></label>
<input type="text" name="luogo" required value="{{ values.luogo }}">
{% endif %}
<br>
<br>
<label><b>{{ 'Others notes (ex. others infos)'|t }}</b></label><br>

View File

@ -1,6 +1,7 @@
{% extends "base.html" %}
{% block content %}
<script src="resources/dist/maps.js"></script>
<style>
#add {
@ -87,7 +88,7 @@
</tbody>
</table>
<script>
window.loadTable("services");
window.loadTable("services", true, 120000);
</script>
</div>
<br>

View File

@ -1,6 +1,7 @@
{% extends "base.html" %}
{% block content %}
<script src="resources/dist/maps.js"></script>
<style>
#add {
@ -85,7 +86,7 @@
</tbody>
</table>
<script>
window.loadTable("trainings");
window.loadTable("trainings", true, 120000);
</script>
</div>
<br>

View File

@ -74,5 +74,8 @@ return [
"Add service" => "Add service",
"Add training" => "Add training",
"You are offline" => "You are offline",
"Last update" => "Last update"
"Last update" => "Last update",
"Search" => "Search",
"Search results" => "Search results",
"No results found" => "No results found"
];

View File

@ -74,5 +74,8 @@ return [
"Add service" => "Aggiungi intervento",
"Add training" => "Aggiungi esercitazione",
"You are offline" => "Sei offline",
"Last update" => "Ultimo aggiornamento"
"Last update" => "Ultimo aggiornamento",
"Search" => "Cerca",
"Search results" => "Risultati della ricerca",
"No results found" => "Nessun risultato trovato"
];