1
0
mirror of https://github.com/elisspace/FxLifeSheet.git synced 2026-08-29 15:44:00 +00:00

Add support for group by week

This commit is contained in:
Felix Krause
2020-12-13 18:48:56 +01:00
parent bbc51a3147
commit d26324fd80
4 changed files with 183 additions and 166 deletions

View File

@@ -1,15 +1,14 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'airbnb-base',
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
},
};
env: {
browser: true,
es2021: true,
},
extends: [
'airbnb-base',
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {},
};

View File

@@ -30,6 +30,8 @@ class API
row[:sum] = row[:sum].truncate(5).to_s('F').to_f # convert from BigFloat to float
if group_by == :yearmonth
row[:as_date] = Date.strptime(row[:yearmonth].to_s, "%Y%m")
elsif group_by == :yearweek
row[:as_date] = Date.strptime(row[:yearweek].to_s, "%Y%W")
else
raise "not yet implemented"
end

View File

@@ -1,13 +1,14 @@
<html>
<head>
<head>
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
<link rel="stylesheet" href="style.css">
<meta charset="utf-8">
</head>
<body>
</head>
<body>
<form id="mainForm" onSubmit="return false;">
<span id="keysContainer">
<span id="keysContainer">
<table id="keysTable">
<tr>
<th>Key</th>
@@ -15,33 +16,33 @@
<th>Shown</th>
</tr>
<tr>
<td><select class="keys" id="keys-0" onchange="updateKeys(0)" /></td>
<td><input type="checkbox" id="keys-avg-0" onchange="updateKeys(0)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-0" onchange="updateKeys(0)" checked="checked" /></td>
<td><select class="keys" id="keys-0" onchange="reloadIndex(0)" /></td>
<td><input type="checkbox" id="keys-avg-0" onchange="reloadIndex(0)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-0" onchange="reloadIndex(0)" checked="checked" /></td>
</tr>
<tr>
<td><select class="keys" id="keys-1" onchange="updateKeys(1)" /></td>
<td><input type="checkbox" id="keys-avg-1" onchange="updateKeys(1)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-1" onchange="updateKeys(1)" checked="checked" /></td>
<td><select class="keys" id="keys-1" onchange="reloadIndex(1)" /></td>
<td><input type="checkbox" id="keys-avg-1" onchange="reloadIndex(1)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-1" onchange="reloadIndex(1)" checked="checked" /></td>
</tr>
<tr>
<td><select class="keys" id="keys-2" onchange="updateKeys(2)" /></td>
<td><input type="checkbox" id="keys-avg-2" onchange="updateKeys(2)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-2" onchange="updateKeys(2)" checked="checked" /></td>
<td><select class="keys" id="keys-2" onchange="reloadIndex(2)" /></td>
<td><input type="checkbox" id="keys-avg-2" onchange="reloadIndex(2)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-2" onchange="reloadIndex(2)" checked="checked" /></td>
</tr>
<tr>
<td><select class="keys" id="keys-3" onchange="updateKeys(3)" /></td>
<td><input type="checkbox" id="keys-avg-3" onchange="updateKeys(3)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-3" onchange="updateKeys(3)" checked="checked" /></td>
<td><select class="keys" id="keys-3" onchange="reloadIndex(3)" /></td>
<td><input type="checkbox" id="keys-avg-3" onchange="reloadIndex(3)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-3" onchange="reloadIndex(3)" checked="checked" /></td>
</tr>
<tr>
<td><select class="keys" id="keys-4" onchange="updateKeys(4)" /></td>
<td><input type="checkbox" id="keys-avg-4" onchange="updateKeys(4)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-4" onchange="updateKeys(4)" checked="checked" /></td>
<td><select class="keys" id="keys-4" onchange="reloadIndex(4)" /></td>
<td><input type="checkbox" id="keys-avg-4" onchange="reloadIndex(4)" checked="checked" /></td>
<td><input type="checkbox" id="keys-show-4" onchange="reloadIndex(4)" checked="checked" /></td>
</tr>
</table>
</span>
<span id="attributesContainer">
<span id="attributesContainer">
<h2>Attributes</h2>
<table id="attributesTable">
<tr>
@@ -53,14 +54,24 @@
</select>
</td>
</tr>
<tr>
<td>Group By</td>
<td>
<select id="group-by" onchange="updateGroupBy()">
<option value="month" selected="selected">Month</option>
<option value="week">Week</option>
</select>
</td>
</tr>
<tr>
<td>Start date</td>
<td><input type="text" value="2019-04" id="start-date" name="start-date" onchange="updatedAttribute()" /></td>
<td><input type="text" value="2019-04" id="start-date" name="start-date" onchange="reloadAllData()" /></td>
</tr>
</table>
</span>
</form>
<div id='myGraph' />
</body>
<script type="text/javascript" src="/frontend.js"></script>
</html>
</body>
<script type="text/javascript" src="/frontend.js"></script>
</html>

View File

@@ -1,157 +1,162 @@
const host = 'http://127.0.0.1:4567';
let keys = [];
const allData = [];
let groupBy = 'month';
// Multiple axis https://plotly.com/javascript/multiple-axes/
for (const currentIndex of Array(5).keys()) {
const current = {
x: [],
y: [],
name: `yaxis${currentIndex + 1} data`,
type: 'scatter',
line: { shape: 'spline' },
};
if (currentIndex > 0) { current.yaxis = `y${currentIndex + 1}`; }
allData.push(current);
const current = {
x: [],
y: [],
name: `yaxis${currentIndex + 1} data`,
type: 'scatter',
line: { shape: 'spline' },
};
if (currentIndex > 0) { current.yaxis = `y${currentIndex + 1}`; }
allData.push(current);
}
console.log(allData);
const layout = {
title: 'Life Sheet Data',
barmode: 'group',
yaxis: {
titlefont: { color: '#1f77b4' },
tickfont: { color: '#1f77b4' },
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis2: {
titlefont: { color: '#ff7f0e' },
tickfont: { color: '#ff7f0e' },
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis3: {
titlefont: { color: '#d62728' },
tickfont: { color: '#d62728' },
anchor: 'x',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis4: {
titlefont: { color: '#9467bd' },
tickfont: { color: '#9467bd' },
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis5: {
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
title: 'Life Sheet Data',
barmode: 'group',
yaxis: {
titlefont: { color: '#1f77b4' },
tickfont: { color: '#1f77b4' },
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis2: {
titlefont: { color: '#ff7f0e' },
tickfont: { color: '#ff7f0e' },
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis3: {
titlefont: { color: '#d62728' },
tickfont: { color: '#d62728' },
anchor: 'x',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis4: {
titlefont: { color: '#9467bd' },
tickfont: { color: '#9467bd' },
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
yaxis5: {
anchor: 'free',
overlaying: 'y',
showgrid: false,
zeroline: false,
showticklabels: false,
},
};
Plotly.newPlot('myGraph', allData, layout);
function loadKeys(callback) {
httpGetAsync(`${host}/keys`, (data) => {
keys = data;
selects = document.getElementsByClassName('keys');
for (let i = 0; i < selects.length; i++) {
data.forEach((row) => {
const opt = document.createElement('option');
opt.value = row.key;
opt.innerHTML = `${row.key} (${row.count})`;
selects[i].appendChild(opt);
});
}
callback(keys);
});
}
function updateKeys(index) {
select = document.getElementById(`keys-${index}`);
loadData(select.value, index);
}
function updatedAttribute() {
for (const currentIndex of Array(5).keys()) {
updateKeys(currentIndex);
}
httpGetAsync(`${host}/keys`, (data) => {
keys = data;
selects = document.getElementsByClassName('keys');
for (let i = 0; i < selects.length; i++) {
data.forEach((row) => {
const opt = document.createElement('option');
opt.value = row.key;
opt.innerHTML = `${row.key} (${row.count})`;
selects[i].appendChild(opt);
});
}
callback(keys);
});
}
function updateGraphType() {
const graphType = document.getElementById('graph-type').value;
for (let i = 0; i < allData.length; i++) {
allData[i].type = graphType;
if (graphType == 'scatter') {
allData[i].yaxis = allData[i].yaxisBak;
} else {
allData[i].yaxisBak = allData[i].yaxis;
delete allData[i].yaxis;
const graphType = document.getElementById('graph-type').value;
for (let i = 0; i < allData.length; i++) {
allData[i].type = graphType;
if (graphType == 'scatter') {
allData[i].yaxis = allData[i].yaxisBak;
} else {
allData[i].yaxisBak = allData[i].yaxis;
delete allData[i].yaxis;
}
}
}
Plotly.redraw('myGraph');
Plotly.redraw('myGraph');
}
function loadData(key, index) {
// TODO: remove the line below
select = document.getElementById(`keys-${index}`);
select.value = key;
function updateGroupBy() {
groupBy = document.getElementById("group-by").value;
reloadAllData();
}
const startDate = document.getElementById('start-date');
const isShown = document.getElementById(`keys-show-${index}`).checked;
function updateKeyForIndex(key, index) {
document.getElementById(`keys-${index}`).value = key;
reloadIndex(index);
}
if (isShown) {
httpGetAsync(`${host}/data?group_by=month&key=${key}&start_date=${startDate.value}`, (data) => {
allData[index].x = data.rows.map((r) => r.as_date);
if (document.getElementById(`keys-avg-${index}`).checked) {
allData[index].y = data.rows.map((r) => Math.round(r.avg * 1000) / 1000);
} else {
allData[index].y = data.rows.map((r) => Math.round(r.sum * 1000) / 1000);
}
allData[index].name = key;
function reloadIndex(index) {
const key = document.getElementById(`keys-${index}`).value;
const startDate = document.getElementById('start-date');
const isShown = document.getElementById(`keys-show-${index}`).checked;
Plotly.redraw('myGraph');
console.log(allData);
console.log(layout);
});
} else {
allData[index].y = [];
Plotly.redraw('myGraph');
}
if (isShown) {
httpGetAsync(`${host}/data?group_by=${groupBy}&key=${key}&start_date=${startDate.value}`, (data) => {
allData[index].x = data.rows.map((r) => r.as_date);
if (document.getElementById(`keys-avg-${index}`).checked) {
allData[index].y = data.rows.map((r) => Math.round(r.avg * 1000) / 1000);
} else {
allData[index].y = data.rows.map((r) => Math.round(r.sum * 1000) / 1000);
}
allData[index].name = key;
Plotly.redraw('myGraph');
console.log(allData);
console.log(layout);
});
} else {
allData[index].y = [];
Plotly.redraw('myGraph');
}
}
function httpGetAsync(theUrl, callback) {
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
callback(JSON.parse(xmlHttp.responseText));
}
};
xmlHttp.open('GET', theUrl, true);
xmlHttp.send(null);
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
callback(JSON.parse(xmlHttp.responseText));
}
};
xmlHttp.open('GET', theUrl, true);
xmlHttp.send(null);
}
loadKeys(() => {
loadData(keys[0].key, 0);
loadData(keys[1].key, 1);
loadData(keys[2].key, 2);
loadData(keys[3].key, 3);
loadData(keys[4].key, 4);
// loadData('mood', 0);
// loadData('excitedAboutFuture', 1);
// loadData('sleepDurationWithings', 2);
// loadData('bedTime', 3);
// loadData('gym', 4);
updateKeyForIndex('mood', 0);
updateKeyForIndex('excitedAboutFuture', 1);
updateKeyForIndex('sleepDurationWithings', 2);
updateKeyForIndex('bedTime', 3);
updateKeyForIndex('gym', 4);
// reloadAllData();
// updateKeyForIndex(keys[0].key, 0);
// updateKeyForIndex(keys[1].key, 1);
// updateKeyForIndex(keys[2].key, 2);
// updateKeyForIndex(keys[3].key, 3);
// updateKeyForIndex(keys[4].key, 4);
});
function reloadAllData() {
for (const currentIndex of Array(5).keys()) {
reloadIndex(currentIndex);
}
}