Add page to export files from Stopwatch, save files in better format and with better filename

pull/205/head
Gordon Williams 2020-04-03 15:15:06 +01:00
parent 9b918055da
commit f66aab5823
6 changed files with 128 additions and 28 deletions

View File

@ -392,7 +392,8 @@
{ "id": "swatch",
"name": "Stopwatch",
"icon": "stopwatch.png",
"version":"0.03",
"version":"0.04",
"interface": "interface.html",
"description": "Simple stopwatch with Lap Time logging to a JSON file",
"tags": "health",
"allow_emulator":true,

View File

@ -11,17 +11,7 @@ var domRecords = document.getElementById("records");
function saveRecord(record,name) {
var csv = `${record.map(rec=>[rec.time, rec.bpm, rec.confidence].join(",")).join("\n")}`;
var a = document.createElement("a"),
file = new Blob([csv], {type: "Comma-separated value file"});
var url = URL.createObjectURL(file);
a.href = url;
a.download = name+".csv";
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
Util.saveCSV(name, csv);
}

View File

@ -3,3 +3,4 @@
Lap log now scrolls into 2nd column after 18th entry, able to display 36 entries before going off screen
0.03: Added ability to save Lap log as a date named JSON file into memory
Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running
0.04: Changed save file filename, add interface.html to allow laps to be loaded

View File

@ -0,0 +1,90 @@
<html>
<head>
<link rel="stylesheet" href="../../css/spectre.min.css">
</head>
<body>
<div id="records"></div>
<script src="../../lib/interface.js"></script>
<script>
var domRecords = document.getElementById("records");
function getLapTimes() {
Util.showModal("Loading Lap Times...");
domRecords.innerHTML = "";
Puck.eval('require("Storage").list(/^swatch.*\.json/).map(fn=>({n:fn,d:require("Storage").readJSON(fn,1)}))',lapData=>{
var html = `<div class="container">
<div class="columns">\n`;
lapData.forEach((lap,lapIndex) => {
lap.date = lap.n.substr(7,16).replace("_"," ");
html += `
<div class="column col-12">
<div class="card-header">
<div class="card-title h5">${lap.date}</div>
<div class="card-subtitle text-gray">${lap.d.length} Laps</div>
</div>
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>lap</th>
<th>time</th>
</tr>
</thead>
<tbody>
${ lap.d.map((d,n)=>`<tr><td>${n+1}</td><td>${d}</td></tr>`).join("\n") }
</tbody>
</table>
</div>
<div class="card-footer">
<button class="btn btn-primary" idx="${lapIndex}" task="download">Download</button>
<button class="btn btn-default" idx="${lapIndex}" task="delete">Delete</button>
</div>
</div>
`;
});
if (lapData.length==0) {
html += `
<div class="column col-12">
<div class="card-header">
<div class="card-title h5">No record</div>
<div class="card-subtitle text-gray">No laps recorded</div>
</div>
</div>
`;
}
html += `
</div>
</div>`;
domRecords.innerHTML = html;
Util.hideModal();
var buttons = domRecords.querySelectorAll("button");
for (var i=0;i<buttons.length;i++) {
buttons[i].addEventListener("click",event => {
var button = event.currentTarget;
var lapIndex = parseInt(button.getAttribute("idx"));
var lap = lapData[lapIndex];
if (!lap) throw new Error("Invalid index!");
var task = button.getAttribute("task");
if (task=="delete") {
Util.showModal("Deleting lap time...");
Util.eraseStorage(lap.n,()=>{
Util.hideModal();
getLapTimes();
});
}
if (task=="download") {
Util.saveCSV(lap.n.slice(0,-5)+".csv", lap.d.map((d,n)=>[n+1,d].join(",")).join("\n"));
}
});
}
})
}
function onInit() {
getLapTimes();
}
</script>
</body>
</html>

View File

@ -4,7 +4,6 @@ var started = false;
var timeY = 60;
var hsXPos = 0;
var lapTimes = [];
var saveTimes = [];
var displayInterval;
function timeToText(t) {
@ -25,7 +24,7 @@ function updateLabels() {
for (var i in lapTimes) {
if (i<18)
{g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);}
else
else
{g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-18)*8);}
}
drawsecs();
@ -51,10 +50,8 @@ function drawms() {
g.clearRect(hsXPos,timeY,220,timeY+20);
g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10);
}
function saveconvert() {
for (var v in lapTimes){
saveTimes[v]=v+1+"-"+timeToText(lapTimes[(lapTimes.length-1)-v]);
}
function getLapTimesArray() {
return lapTimes.map(timeToText).reverse();
}
setWatch(function() { // Start/stop
@ -80,16 +77,21 @@ setWatch(function() { // Start/stop
}, BTN2, {repeat:true});
setWatch(function() { // Lap
Bangle.beep();
if (started) tCurrent = Date.now();
lapTimes.unshift(tCurrent-tStart);
tStart = tCurrent;
if (!started)
{
var timenow= Date();
saveconvert();
require("Storage").writeJSON("StpWch-"+timenow.toString(), saveTimes);
if (started) {
tCurrent = Date.now();
lapTimes.unshift(tCurrent-tStart);
}
tStart = tCurrent;
if (!started) { // save
var timenow= Date();
var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json";
// this maxes out the 28 char maximum
require("Storage").writeJSON(filename, getLapTimesArray());
E.showMessage("Laps Saved","Stopwatch");
setTimeout(updateLabels, 1000);
} else {
updateLabels();
}
updateLabels();
}, BTN1, {repeat:true});
setWatch(function() { // Reset
if (!started) {

View File

@ -39,7 +39,10 @@ var Util = {
window.postMessage({type:"readstoragefile",data:filename,id:__id});
},
eraseStorageFile : function(filename,callback) {
Puck.write(`\x10require("Storage").open(${JSON.stringify(filename)}","r").erase()\n`,callback);
Puck.write(`\x10require("Storage").open(${JSON.stringify(filename)},"r").erase()\n`,callback);
},
eraseStorage : function(filename,callback) {
Puck.write(`\x10require("Storage").erase(${JSON.stringify(filename)})\n`,callback);
},
showModal : function(title) {
if (!Util.domModal) {
@ -66,6 +69,19 @@ var Util = {
hideModal : function() {
if (!Util.domModal) return;
Util.domModal.classList.remove("active");
},
saveCSV : function(filename, csvData) {
var a = document.createElement("a"),
file = new Blob([csvData], {type: "Comma-separated value file"});
var url = URL.createObjectURL(file);
a.href = url;
a.download = filename+".csv";
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
};
window.addEventListener("message", function(event) {