Rewrite to use Framework7, multiple pages, and better UX in general
@ -2,23 +2,35 @@
|
||||
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||
<properties>
|
||||
<entry key="DownloadThreads">1</entry>
|
||||
<entry key="TileSortingPolicy">2</entry>
|
||||
<entry key="ProxyServerUser"></entry>
|
||||
<entry key="UrlSquare.Radius">5</entry>
|
||||
<entry key="BBoxLatLon.MinLon">-112.1429</entry>
|
||||
<entry key="GPX.Corridor">0</entry>
|
||||
<entry key="ProxyServerPassword"></entry>
|
||||
<entry key="WaitSeconds">2</entry>
|
||||
<entry key="InputPanelIndex">1</entry>
|
||||
<entry key="MinimumAgeInDays">7</entry>
|
||||
<entry key="LastZoom">16</entry>
|
||||
<entry key="LastZoom">12-16</entry>
|
||||
<entry key="WaitAfterNrTiles">false</entry>
|
||||
<entry key="BBoxXY.MaxX">0</entry>
|
||||
<entry key="TileServer">https://maps.netsyms.net/styles/klokantech-basic/</entry>
|
||||
<entry key="SlippyMapSaveTiles">false</entry>
|
||||
<entry key="BBoxXY.MaxY">0</entry>
|
||||
<entry key="SlippyMapNoDownload">false</entry>
|
||||
<entry key="UseProxyServer">false</entry>
|
||||
<entry key="GPX.GpxFile"></entry>
|
||||
<entry key="ShowTilePreview">true</entry>
|
||||
<entry key="LastOutoutFolder">/home/skylar/Documents/Projects/Sources/PackageNotice/www/assets/tiles</entry>
|
||||
<entry key="TileSortingPolicy">2</entry>
|
||||
<entry key="ProxyServerUser"></entry>
|
||||
<entry key="BBoxLatLon.MaxLon">-111.7557</entry>
|
||||
<entry key="BBoxXY.MinX">0</entry>
|
||||
<entry key="BBoxXY.MinY">0</entry>
|
||||
<entry key="WaitSeconds">2</entry>
|
||||
<entry key="WaitNrTiles">10</entry>
|
||||
<entry key="ProxyServer"></entry>
|
||||
<entry key="ProxyServerPort"></entry>
|
||||
<entry key="UseProxyServerAuth">false</entry>
|
||||
<entry key="BBoxLatLon.MaxLat">46.7384</entry>
|
||||
<entry key="OverwriteExistingFiles">true</entry>
|
||||
<entry key="TileServer">https://maps.netsyms.net/styles/klokantech-basic/</entry>
|
||||
<entry key="SlippyMapSaveTiles">false</entry>
|
||||
<entry key="SlippyMapNoDownload">false</entry>
|
||||
<entry key="UseProxyServer">false</entry>
|
||||
<entry key="ShowTilePreview">true</entry>
|
||||
<entry key="LastOutoutFolder">/home/skylar/Documents/Projects/Sources/PackageNotice/www/assets/tiles</entry>
|
||||
<entry key="BBoxLatLon.MinLat">46.5127</entry>
|
||||
<entry key="UrlSquare.PasteUrl"></entry>
|
||||
</properties>
|
||||
|
10
config.xml
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="com.netsyms.PackageNotice" version="1.0.0">
|
||||
<name>PackageNotice</name>
|
||||
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="com.netsyms.PackageHelper" version="1.0.0">
|
||||
<name>PackageHelper</name>
|
||||
<description>
|
||||
A sample Apache Cordova application that responds to the deviceready event.
|
||||
Assistant app for door-to-door package delivery.
|
||||
</description>
|
||||
<author email="dev@cordova.apache.org" href="http://cordova.io">
|
||||
Apache Cordova Team
|
||||
<author email="contact@netsyms.com" href="https://netsyms.com">
|
||||
Netsyms Technologies
|
||||
</author>
|
||||
<content src="index.html"/>
|
||||
<plugin name="cordova-plugin-whitelist" spec="1"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<properties>
|
||||
<entry key="Type">BBoxLatLon</entry>
|
||||
<entry key="OutputLocation">/home/skylar/Documents/Projects/Sources/PackageNotice/www/assets/tiles</entry>
|
||||
<entry key="TileServer">Mapnik</entry>
|
||||
<entry key="TileServer">https://maps.netsyms.net/styles/klokantech-basic/</entry>
|
||||
<entry key="MaxLat">46.7384</entry>
|
||||
<entry key="OutputZoomLevel">12,13,14,15</entry>
|
||||
<entry key="MaxLon">-111.7557</entry>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<type>org.netbeans.modules.web.clientproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/clientside-project/1">
|
||||
<name>PackageNotice</name>
|
||||
<name>PackageHelper</name>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
BIN
www/assets/audio/alert.echo.mp3
Normal file
BIN
www/assets/audio/error.mp3
Normal file
BIN
www/assets/audio/ok.mp3
Normal file
BIN
www/assets/images/box-alert.png
Normal file
After Width: | Height: | Size: 943 B |
79
www/assets/images/box-alert.svg
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
data-prefix="fas"
|
||||
data-icon="box-alt"
|
||||
class="svg-inline--fa fa-box-alt fa-w-14"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
version="1.1"
|
||||
id="svg916"
|
||||
sodipodi:docname="box-alert.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
inkscape:export-filename="/home/skylar/Documents/Projects/Sources/PackageHelper/www/assets/images/box-alert.png"
|
||||
inkscape:export-xdpi="10.687501"
|
||||
inkscape:export-ydpi="10.687501">
|
||||
<metadata
|
||||
id="metadata922">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs920" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1013"
|
||||
id="namedview918"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0413252"
|
||||
inkscape:cx="235.33213"
|
||||
inkscape:cy="193.55813"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg916" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ff9800;stroke-width:0.875"
|
||||
d="M 445.8125,193.525 401.5375,60.699994 C 395.85001,43.549997 379.8375,31.999996 361.725,31.999996 H 238 V 200 h 208.8625 c -0.35,-2.1875 -0.35,-4.375 -1.05,-6.475 z M 210,31.999996 H 86.275001 C 68.1625,31.999996 52.15,43.549997 46.4625,60.699994 L 2.1874999,193.525 C 1.4875,195.625 1.4875,197.8125 1.1375,200 H 210 Z M 2.0000001e-7,228 V 438 C 2.0000001e-7,461.1875 18.8125,480 42,480 H 406.00001 C 429.1875,480 448,461.1875 448,438 V 228 Z"
|
||||
id="path2" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="opacity:1;fill:#fff9c4;fill-opacity:1;stroke:#fff9c4;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path949"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="224"
|
||||
sodipodi:cy="382.43686"
|
||||
sodipodi:r1="120.92724"
|
||||
sodipodi:r2="60.463619"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 328.72606,442.90048 -209.45212,0 L 224,261.50962 Z"
|
||||
inkscape:transform-center-y="-30.231809" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
16
www/assets/js/audio.js
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
|
||||
var sfx = {
|
||||
"alert": new Audio("assets/audio/alert.echo.mp3"),
|
||||
"ok": new Audio("assets/audio/ok.mp3"),
|
||||
"error": new Audio("assets/audio/error.mp3")
|
||||
};
|
||||
|
||||
function playSound(sound) {
|
||||
sfx[sound].play();
|
||||
}
|
91
www/assets/js/list.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
$(".view-main").on("click", "#addresslist .package-list-item .item-content", function () {
|
||||
var pid = $(this).data("packageid");
|
||||
if (typeof packages[pid].delivered == "undefined" || packages[pid].delivered == false) {
|
||||
packages[pid].delivered = true;
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
loadPackageList();
|
||||
} else {
|
||||
app.dialog.confirm(
|
||||
packages[pid].address,
|
||||
"Mark Undelivered",
|
||||
function () {
|
||||
// undeliver
|
||||
packages[pid].delivered = false;
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
loadPackageList();
|
||||
},
|
||||
function () {
|
||||
// cancel
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$(".view-main").on("mousedown", "#addresslist .package-list-item .item-content", function (e) {
|
||||
if (e.button == 2) {
|
||||
confirmDeletePackage($(this).data("packageid"));
|
||||
}
|
||||
});
|
||||
|
||||
$(".view-main").on("swipeout:delete", "#addresslist .package-list-item", function () {
|
||||
console.log("Deleting package", $(this).data("packageid"));
|
||||
deletePackage($(this).data("packageid"));
|
||||
});
|
||||
|
||||
function loadPackageList() {
|
||||
$("#addresslist").html("");
|
||||
|
||||
for (var i = 0; i < packages.length; i++) {
|
||||
var icon = "fas fa-box-open";
|
||||
var classes = "";
|
||||
if (packages[i].delivered == true) {
|
||||
icon = "fas fa-check";
|
||||
classes = "text-color-green";
|
||||
}
|
||||
$("#addresslist").append(
|
||||
'<li class="swipeout package-list-item" data-packageid="' + i + '">'
|
||||
+ '<div class="item-content swipeout-content ' + classes + '" data-packageid="' + i + '" data-latitude="' + packages[i].coords[0] + '" data-longitude="' + packages[i].coords[1] + '">'
|
||||
+ ' <div class="item-media">'
|
||||
+ ' <i class="icon ' + icon + '"></i>'
|
||||
+ ' </div>'
|
||||
+ ' <div class="item-inner">'
|
||||
+ ' <div class="item-title">'
|
||||
+ ' ' + packages[i].address
|
||||
+ ' </div>'
|
||||
+ ' <div class="item-footer">'
|
||||
+ ' <span class="distance">... m</span>'
|
||||
+ ' </div>'
|
||||
+ ' </div>'
|
||||
+ '</div>'
|
||||
+ '<div class="swipeout-actions-right">'
|
||||
+ ' <a href="#" class="swipeout-delete">Delete</a>'
|
||||
+ '</div>'
|
||||
+ '</li>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteAllPackages() {
|
||||
app.dialog.confirm(
|
||||
"Really delete all packages from list?",
|
||||
"Clear Packages",
|
||||
function () {
|
||||
// clear
|
||||
packages = [];
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
loadPackageList();
|
||||
if (map != null) {
|
||||
map.updatePackageLayer(packages);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
// cancel
|
||||
}
|
||||
);
|
||||
}
|
62
www/assets/js/main.js
Normal file
@ -0,0 +1,62 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var $$ = Dom7;
|
||||
|
||||
// Detect platform and run platform-specific setup code
|
||||
// for Cordova, NW.js, or the browser
|
||||
initPlatform();
|
||||
|
||||
var app = new Framework7({
|
||||
root: "#app",
|
||||
name: "PackageHelper",
|
||||
id: "com.netsyms.PackageHelper",
|
||||
theme: "md",
|
||||
card: {
|
||||
swipeToClose: false
|
||||
},
|
||||
popup: {
|
||||
backdrop: true
|
||||
},
|
||||
init: true,
|
||||
initOnDeviceReady: false,
|
||||
routes: routes
|
||||
});
|
||||
|
||||
var mainView = app.views.create('.view-main', {
|
||||
url: "/"
|
||||
});
|
||||
|
||||
var router = mainView.router;
|
||||
|
||||
function restartApplication() {
|
||||
window.location = "index.html";
|
||||
}
|
||||
|
||||
|
||||
router.on("pageInit", function (pagedata) {
|
||||
pagedata.$el.find('script').each(function (el) {
|
||||
if ($$(this).attr('src')) {
|
||||
var s = document.createElement('script');
|
||||
s.src = $$(this).attr('src');
|
||||
$$('head').append(s);
|
||||
} else {
|
||||
eval($$(this).text());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.on("routeChange", function (newRoute) {
|
||||
console.log(newRoute);
|
||||
if (newRoute == "home") {
|
||||
router.refreshPage();
|
||||
}
|
||||
});
|
||||
|
||||
// Set alert radius to 100 meters by default
|
||||
if (localStorage.getItem("alertradius") == null) {
|
||||
localStorage.setItem("alertradius", 100);
|
||||
}
|
||||
|
||||
router.navigate("/home");
|
70
www/assets/js/manage.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
|
||||
$("#addpackagebtn").click(function () {
|
||||
if ($("input[name=number]").val().trim() == "") {
|
||||
playSound("error");
|
||||
app.toast.show({
|
||||
text: "Please fill in a street number.",
|
||||
position: "bottom",
|
||||
destroyOnClose: true,
|
||||
closeTimeout: 1000 * 10
|
||||
});
|
||||
return;
|
||||
}
|
||||
if ($("input[name=street]").val().trim() == "") {
|
||||
playSound("error");
|
||||
app.toast.show({
|
||||
text: "Please fill in a street name.",
|
||||
position: "bottom",
|
||||
destroyOnClose: true,
|
||||
closeTimeout: 1000 * 10
|
||||
});
|
||||
return;
|
||||
}
|
||||
if ($("input[name=citystate]").val().trim() == "") {
|
||||
playSound("error");
|
||||
app.toast.show({
|
||||
text: "Please fill in a city and state.",
|
||||
position: "bottom",
|
||||
destroyOnClose: true,
|
||||
closeTimeout: 1000 * 10
|
||||
});
|
||||
return;
|
||||
}
|
||||
var address = ($("input[name=number]").val() + " " + $("input[name=street]").val()).toUpperCase();
|
||||
$.getJSON(geocodeapi, {
|
||||
address: address + " " + $("input[name=citystate]").val().toUpperCase()
|
||||
}, function (resp) {
|
||||
if (resp.status == "OK") {
|
||||
packages.push({
|
||||
"address": address,
|
||||
"coords": [
|
||||
resp.coords[0],
|
||||
resp.coords[1]
|
||||
]
|
||||
});
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
|
||||
playSound("ok");
|
||||
|
||||
app.toast.show({
|
||||
text: 'Package Added!<br><span style="font-size: 80%;">' + address + "</span>",
|
||||
position: "bottom",
|
||||
destroyOnClose: true,
|
||||
closeTimeout: 1000 * 2
|
||||
});
|
||||
|
||||
if (map != null) {
|
||||
map.updatePackageLayer(packages);
|
||||
}
|
||||
} else {
|
||||
playSound("error");
|
||||
app.dialog.alert(resp.message, "Error");
|
||||
}
|
||||
});
|
||||
});
|
@ -19,9 +19,64 @@ var geoerrorcount = 0;
|
||||
|
||||
var gotfirstfix = false;
|
||||
|
||||
var map = leafletMap();
|
||||
var map = null;
|
||||
|
||||
function createMap() {
|
||||
map = leafletMap();
|
||||
map.updatePackageLayer(packages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the toggle button on the popup sheet do things
|
||||
*/
|
||||
$("#app").on("click", "#package-info-sheet #package-info-toggle-status", function () {
|
||||
var pid = $(this).data("packageid");
|
||||
if (typeof packages[pid].delivered == "undefined" || packages[pid].delivered == false) {
|
||||
packages[pid].delivered = true;
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
map.updatePackageLayer(packages);
|
||||
openPackageInfoSheet(packages[pid], true);
|
||||
} else {
|
||||
app.dialog.confirm(
|
||||
packages[pid].address,
|
||||
"Mark Undelivered",
|
||||
function () {
|
||||
// undeliver
|
||||
packages[pid].delivered = false;
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
map.updatePackageLayer(packages);
|
||||
openPackageInfoSheet(packages[pid], true);
|
||||
},
|
||||
function () {
|
||||
// cancel
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function openPackageInfoSheet(package, refreshOnly) {
|
||||
if (typeof refreshOnly == "undefined") {
|
||||
refreshOnly = false;
|
||||
}
|
||||
$("#package-info-toggle-status").data("packageid", packages.findIndex(function (p) {
|
||||
return p == package;
|
||||
}));
|
||||
$("#package-info-address").text(package.address);
|
||||
if (package.delivered) {
|
||||
$("#package-info-delivery-status").html('<span class="text-color-green"><i class="fas fa-check-circle"></i> Delivered</span>');
|
||||
$("#package-info-toggle-status").text("Mark undelivered");
|
||||
} else {
|
||||
$("#package-info-delivery-status").html('<i class="fas fa-circle"></i> Not delivered');
|
||||
$("#package-info-toggle-status").text("Mark delivered");
|
||||
}
|
||||
if (!refreshOnly) {
|
||||
app.sheet.create({el: "#package-info-sheet"}).open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: make app location work before map is opened for first time
|
||||
*/
|
||||
if ("geolocation" in navigator) {
|
||||
navigator.geolocation.watchPosition(function (position) {
|
||||
userPosition = position;
|
||||
@ -31,9 +86,10 @@ if ("geolocation" in navigator) {
|
||||
var currentTimestamp = Math.floor(Date.now() / 1000);
|
||||
if (lastGpsUpdateTimestamp < (currentTimestamp - 10)) {
|
||||
updateDistances(position.coords.latitude, position.coords.longitude);
|
||||
map.updatePackageLayer(packages);
|
||||
lastGpsUpdateTimestamp = currentTimestamp;
|
||||
for (var i = 0; i < packages.length; i++) {
|
||||
if (packages[i].distance * 1 < $("#alertdistance").val() * 1) {
|
||||
if (packages[i].distance * 1 < localStorage.getItem("alertradius") * 1) {
|
||||
|
||||
if (packages[i].lastAlert > currentTimestamp - 30) {
|
||||
continue;
|
||||
@ -43,35 +99,16 @@ if ("geolocation" in navigator) {
|
||||
continue;
|
||||
}
|
||||
|
||||
alertsound.play();
|
||||
|
||||
var origbg = $("body").css("background-color");
|
||||
$("#addresslist .list-group-item[data-packageid=" + i + "]").addClass("bg-warning");
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", "orange");
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", origbg);
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", "orange");
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", origbg);
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", "orange");
|
||||
setTimeout(function () {
|
||||
$("body").css("background-color", origbg);
|
||||
}, 500);
|
||||
}, 500);
|
||||
}, 500);
|
||||
}, 500);
|
||||
}, 500);
|
||||
}, 500);
|
||||
|
||||
playSound("alert");
|
||||
|
||||
packages[i].lastAlert = currentTimestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (map == null) {
|
||||
return;
|
||||
}
|
||||
map.locateControl.start();
|
||||
gotfirstfix = true;
|
||||
}
|
||||
@ -88,15 +125,14 @@ if ("geolocation" in navigator) {
|
||||
geoerrorcount++;
|
||||
console.log("Geolocation error #" + geoerrorcount + ": ", error);
|
||||
// Stop showing error toasts if they're happening a lot
|
||||
// if (geoerrorcount > 3) {
|
||||
// return;
|
||||
// }
|
||||
// app.toast.show({
|
||||
// text: '<i class="fas fa-compass"></i> ' + error,
|
||||
// position: "bottom",
|
||||
// destroyOnClose: true,
|
||||
// closeTimeout: 1000 * 4
|
||||
// });
|
||||
if (geoerrorcount <= 3) {
|
||||
app.toast.show({
|
||||
text: '<i class="fas fa-compass"></i> ' + error,
|
||||
position: "bottom",
|
||||
destroyOnClose: true,
|
||||
closeTimeout: 1000 * 3
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,18 +143,24 @@ if ("geolocation" in navigator) {
|
||||
*/
|
||||
function updateDistances(latitude, longitude) {
|
||||
for (var i = 0; i < packages.length; i++) {
|
||||
var distance = getDistance(userPosition.coords.latitude, userPosition.coords.longitude, packages[i].coords[0], packages[i].coords[1]).toFixed(0);
|
||||
var distance = getDistance(latitude, longitude, packages[i].coords[0], packages[i].coords[1]).toFixed(0);
|
||||
packages[i].distance = distance;
|
||||
$("#addresslist .list-group-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"]").data("distance", distance);
|
||||
$("#addresslist .list-group-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"] .distance").text(distance + " m");
|
||||
$("#addresslist .package-list-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"]").data("distance", distance);
|
||||
$("#addresslist .package-list-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"] .distance").text(distance + " m");
|
||||
}
|
||||
}
|
||||
|
||||
function setMapLocation(latitude, longitude) {
|
||||
if (map == null) {
|
||||
return;
|
||||
}
|
||||
map.setMapLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
function animateMapIn(latitude, longitude, zoom, heading) {
|
||||
if (map == null) {
|
||||
return;
|
||||
}
|
||||
if (typeof zoom == 'undefined') {
|
||||
zoom = 14;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ function leafletMap() {
|
||||
|
||||
L.tileLayer('assets/tiles/{z}/{x}/{y}.png', {
|
||||
minZoom: 12,
|
||||
maxZoom: 15,
|
||||
maxZoom: 16,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
|
||||
@ -50,8 +50,16 @@ function leafletMap() {
|
||||
|
||||
data.forEach(function (package) {
|
||||
|
||||
var iconName = "box";
|
||||
|
||||
if (package.delivered) {
|
||||
iconName = "box-check";
|
||||
} else if (package.distance * 1 < localStorage.getItem("alertradius") * 1) {
|
||||
iconName = "box-alert";
|
||||
}
|
||||
|
||||
var icon = L.icon({
|
||||
iconUrl: "assets/images/" + (package.delivered == true ? "box-check.png" : "box.png"),
|
||||
iconUrl: "assets/images/" + iconName + ".png",
|
||||
iconSize: [25, 25],
|
||||
iconAnchor: [12.5, 12.5]
|
||||
});
|
||||
@ -65,7 +73,7 @@ function leafletMap() {
|
||||
icon: icon
|
||||
})
|
||||
.on('click', function () {
|
||||
alert(package.address);
|
||||
openPackageInfoSheet(package);
|
||||
})
|
||||
.addTo(map.packagelayer);
|
||||
});
|
||||
|
43
www/assets/js/packages.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
var packages = [];
|
||||
|
||||
if (localStorage.getItem("packages") != null) {
|
||||
packages = JSON.parse(localStorage.getItem("packages"));
|
||||
}
|
||||
|
||||
function confirmDeletePackage(id) {
|
||||
app.dialog.confirm(
|
||||
"Delete package at " + packages[id].address + "?",
|
||||
"Confirm",
|
||||
function () {
|
||||
// delete
|
||||
packages.splice(id, 1);
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
loadPackageList();
|
||||
},
|
||||
function () {
|
||||
// cancel
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function deletePackage(id) {
|
||||
packages.splice(id, 1);
|
||||
localStorage.setItem("packages", JSON.stringify(packages));
|
||||
loadPackageList();
|
||||
}
|
||||
|
||||
function countRemainingPackages() {
|
||||
var undelivered = 0;
|
||||
for (var i = 0; i < packages.length; i++) {
|
||||
if (packages[i].delivered != true) {
|
||||
undelivered++;
|
||||
}
|
||||
}
|
||||
return undelivered;
|
||||
}
|
223
www/assets/js/platform.js
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
var platform_type = "";
|
||||
|
||||
var platform_theme = "md";
|
||||
|
||||
var app_version = "2.0.0";
|
||||
|
||||
var nw_tray = null;
|
||||
|
||||
var openBrowser = function (url) {
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
var openSystemBrowser = function (url) {
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
var scanBarcode = function (success, error) {
|
||||
app.dialog.alert("You can't scan barcodes with this device.", "Sorry!");
|
||||
}
|
||||
|
||||
var getLocation = function (success, error) {
|
||||
if ("geolocation" in navigator) {
|
||||
navigator.geolocation.getCurrentPosition(function (position) {
|
||||
success(position);
|
||||
}, function (err) {
|
||||
if (typeof error == "function") {
|
||||
error(err.message);
|
||||
}
|
||||
}, {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 5000,
|
||||
maximumAge: 0
|
||||
});
|
||||
} else {
|
||||
if (typeof error == "function") {
|
||||
error("Location is unavailable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var watchLocation = function (success, error) {
|
||||
if ("geolocation" in navigator) {
|
||||
navigator.geolocation.watchPosition(function (position) {
|
||||
success(position);
|
||||
}, function (err) {
|
||||
if (typeof error == "function") {
|
||||
error(err.message);
|
||||
}
|
||||
}, {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 5000,
|
||||
maximumAge: 0
|
||||
});
|
||||
} else {
|
||||
if (typeof error == "function") {
|
||||
error("Location is unavailable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initCordova() {
|
||||
platform_type = "cordova";
|
||||
|
||||
// Handle back button to close things
|
||||
document.addEventListener("backbutton", function (event) {
|
||||
router.back();
|
||||
}, false);
|
||||
|
||||
document.addEventListener("deviceready", function () {
|
||||
app.statusbar.overlaysWebView(true);
|
||||
StatusBar.backgroundColorByHexString("#000000ff");
|
||||
if (cordova.platformId == 'android') {
|
||||
//StatusBar.backgroundColorByHexString("#324150");
|
||||
//StatusBar.styleLightContent();
|
||||
}
|
||||
router.on("routeChange", function (newRoute, previousRoute, router) {
|
||||
if (newRoute.name == "home") {
|
||||
StatusBar.styleDefault();
|
||||
} else {
|
||||
StatusBar.styleLightContent();
|
||||
}
|
||||
});
|
||||
}, false);
|
||||
|
||||
openBrowser = function (url) {
|
||||
cordova.InAppBrowser.open(url, '_blank', 'location=yes');
|
||||
}
|
||||
|
||||
openExternalBrowser = function (url) {
|
||||
window.open(url, '_system', '');
|
||||
}
|
||||
|
||||
scanBarcode = function (success, error) {
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function (result) {
|
||||
if (!result.cancelled) {
|
||||
success(result.text);
|
||||
}
|
||||
},
|
||||
function (err) {
|
||||
if (typeof error == "function") {
|
||||
error(err);
|
||||
}
|
||||
},
|
||||
{
|
||||
showTorchButton: true,
|
||||
prompt: "Find a code",
|
||||
resultDisplayDuration: 0,
|
||||
disableSuccessBeep: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// When running on Android 8.0 (not 7.1.1, not 8.1, just 8.0), the statusbar
|
||||
// height is incorrectly set to 0px, causing the clock and icons to overlap
|
||||
// on the TerranQuest UI.
|
||||
document.addEventListener("deviceready", function () {
|
||||
if (device.platform == "Android" && device.version.startsWith("8.0") && getComputedStyle(document.documentElement).getPropertyValue('--f7-statusbar-height').startsWith("0")) {
|
||||
document.documentElement.style.setProperty('--f7-statusbar-height', '24px');
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function initNW() {
|
||||
platform_type = "nw";
|
||||
platform_theme = "md";
|
||||
|
||||
openBrowser = function (url) {
|
||||
nw.Window.open(url, {
|
||||
id: url
|
||||
}, function (browserwin) {
|
||||
// Add menubar so the user can navigate around if they click a link
|
||||
var browsermenu = new nw.Menu({type: 'menubar'});
|
||||
browsermenu.append(new nw.MenuItem({
|
||||
label: "Back",
|
||||
click: function () {
|
||||
browserwin.window.history.back();
|
||||
}
|
||||
}));
|
||||
browsermenu.append(new nw.MenuItem({
|
||||
label: "Forward",
|
||||
click: function () {
|
||||
browserwin.window.history.forward();
|
||||
}
|
||||
}));
|
||||
browsermenu.append(new nw.MenuItem({
|
||||
label: "Home",
|
||||
click: function () {
|
||||
browserwin.window.location.href = url;
|
||||
}
|
||||
}));
|
||||
browserwin.menu = browsermenu;
|
||||
});
|
||||
}
|
||||
|
||||
openExternalBrowser = function (url) {
|
||||
require('nw.gui').Shell.openExternal(url);
|
||||
}
|
||||
|
||||
$("body").append('<script src="node_modules/@zxing/library/umd/index.min.js"></script>');
|
||||
|
||||
scanBarcode = function (success, error) {
|
||||
$("#web-barcode-ui").removeClass("hidden");
|
||||
// Stolen from https://zxing-js.github.io/library/examples/multi-camera/
|
||||
const codeReader = new ZXing.BrowserMultiFormatReader();
|
||||
console.log('ZXing code reader initialized');
|
||||
codeReader.getVideoInputDevices()
|
||||
.then((videoInputDevices) => {
|
||||
selectedDeviceId = videoInputDevices[0].deviceId;
|
||||
|
||||
codeReader.decodeFromInputVideoDeviceContinuously(selectedDeviceId, 'barcode-viewer', (result, err) => {
|
||||
if (result) {
|
||||
console.log(result);
|
||||
codeReader.reset();
|
||||
$("#web-barcode-ui").addClass("hidden");
|
||||
success(result.text);
|
||||
}
|
||||
if (err && !(err instanceof ZXing.NotFoundException)) {
|
||||
console.error(err);
|
||||
codeReader.reset();
|
||||
$("#web-barcode-ui").addClass("hidden");
|
||||
error(err);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
$("#web-barcode-ui").on("click", function () {
|
||||
codeReader.reset();
|
||||
$("#web-barcode-ui").addClass("hidden");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function initBrowser() {
|
||||
platform_type = "browser";
|
||||
platform_theme = "md";
|
||||
|
||||
openBrowser = function (url) {
|
||||
window.open(url);
|
||||
}
|
||||
}
|
||||
|
||||
function initPlatform() {
|
||||
if (typeof cordova !== 'undefined') {
|
||||
initCordova();
|
||||
} else if (typeof nw !== 'undefined') {
|
||||
initNW();
|
||||
} else {
|
||||
initBrowser();
|
||||
}
|
||||
|
||||
$.getJSON("package.json", function (data) {
|
||||
app_version = data.version;
|
||||
});
|
||||
}
|
BIN
www/assets/tiles/16/12360/23168.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
www/assets/tiles/16/12360/23169.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
www/assets/tiles/16/12360/23170.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
www/assets/tiles/16/12360/23171.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
www/assets/tiles/16/12360/23172.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
www/assets/tiles/16/12360/23173.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
www/assets/tiles/16/12360/23174.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
www/assets/tiles/16/12360/23175.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
www/assets/tiles/16/12360/23176.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12360/23177.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12360/23178.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12360/23179.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
www/assets/tiles/16/12360/23180.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
www/assets/tiles/16/12361/23168.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
www/assets/tiles/16/12361/23169.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
www/assets/tiles/16/12361/23170.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
www/assets/tiles/16/12361/23171.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
www/assets/tiles/16/12361/23172.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
www/assets/tiles/16/12361/23173.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
www/assets/tiles/16/12361/23174.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
www/assets/tiles/16/12361/23175.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
www/assets/tiles/16/12361/23176.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12361/23177.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12361/23178.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12361/23179.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
www/assets/tiles/16/12361/23180.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
www/assets/tiles/16/12362/23168.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
www/assets/tiles/16/12362/23169.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12362/23170.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
www/assets/tiles/16/12362/23171.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
www/assets/tiles/16/12362/23172.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
www/assets/tiles/16/12362/23173.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
www/assets/tiles/16/12362/23174.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
www/assets/tiles/16/12362/23175.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
www/assets/tiles/16/12362/23176.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12362/23177.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
www/assets/tiles/16/12362/23178.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
www/assets/tiles/16/12362/23179.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
www/assets/tiles/16/12362/23180.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
www/assets/tiles/16/12363/23168.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
www/assets/tiles/16/12363/23169.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
www/assets/tiles/16/12363/23170.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
www/assets/tiles/16/12363/23171.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
www/assets/tiles/16/12363/23172.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
www/assets/tiles/16/12363/23173.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
www/assets/tiles/16/12363/23174.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
www/assets/tiles/16/12363/23175.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
www/assets/tiles/16/12363/23176.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
www/assets/tiles/16/12363/23177.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
www/assets/tiles/16/12363/23178.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
www/assets/tiles/16/12363/23179.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
www/assets/tiles/16/12363/23180.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12364/23161.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
www/assets/tiles/16/12364/23162.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
www/assets/tiles/16/12364/23163.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
www/assets/tiles/16/12364/23164.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
www/assets/tiles/16/12364/23165.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
www/assets/tiles/16/12364/23166.png
Normal file
After Width: | Height: | Size: 805 B |
BIN
www/assets/tiles/16/12364/23167.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
www/assets/tiles/16/12364/23168.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
www/assets/tiles/16/12364/23169.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
www/assets/tiles/16/12364/23170.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
www/assets/tiles/16/12364/23171.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
www/assets/tiles/16/12364/23172.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
www/assets/tiles/16/12364/23173.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12364/23174.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12364/23175.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12364/23176.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
www/assets/tiles/16/12364/23177.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
www/assets/tiles/16/12364/23178.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
www/assets/tiles/16/12364/23179.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12364/23180.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
www/assets/tiles/16/12365/23160.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
BIN
www/assets/tiles/16/12365/23161.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
www/assets/tiles/16/12365/23162.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
www/assets/tiles/16/12365/23163.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
www/assets/tiles/16/12365/23164.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
www/assets/tiles/16/12365/23165.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
www/assets/tiles/16/12365/23166.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
www/assets/tiles/16/12365/23167.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
www/assets/tiles/16/12365/23168.png
Normal file
After Width: | Height: | Size: 822 B |
BIN
www/assets/tiles/16/12365/23169.png
Normal file
After Width: | Height: | Size: 8.8 KiB |