Skip to content

Commit 3fae3ef

Browse files
committed
Simple visualizer. More warnings
1 parent 2f43bbc commit 3fae3ef

File tree

7 files changed

+237
-12
lines changed

7 files changed

+237
-12
lines changed

dev-qubes.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
(function () {
2+
const confirmSpendingQubes = window.confirm(
3+
'Click on every Spending Qube once before continuing. Ready?'
4+
);
5+
6+
if (!confirmSpendingQubes) {
7+
alert(
8+
'Please go back and click on every spending qube before downloading your data.'
9+
);
10+
return;
11+
}
12+
13+
function downloadJson(jsonString, label) {
14+
var anchor = document.createElement('a');
15+
anchor.setAttribute(
16+
'href',
17+
'data:application/json;charset=utf-8,' + encodeURIComponent(jsonString)
18+
);
19+
var timestamp = new Date().toISOString().slice(0, 10);
20+
anchor.setAttribute('download', `baqup-${label} ${timestamp}.json`);
21+
anchor.setAttribute('target', '_blank');
22+
anchor.style.display = 'none';
23+
document.body.appendChild(anchor);
24+
25+
anchor.click();
26+
}
27+
28+
const cache = JSON.parse(localStorage.getItem('vuex'));
29+
30+
const currentURL = new URL(window.location.href);
31+
if (
32+
!cache ||
33+
currentURL.protocol !== 'https:' ||
34+
currentURL.hostname !== 'dashboard.qubemoney.com'
35+
) {
36+
alert('You must be viewing Qube and logged in to download your data.');
37+
return;
38+
}
39+
40+
downloadJson(localStorage.getItem('vuex'), 'account');
41+
})();
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
alert('baQup Tools is already running. Please wait for it to finish.');
44
return;
55
}
6+
7+
const confirmSpendingQubes = window.confirm(
8+
'This will download all your transactions as multiple files. Stay on the page until you see the completion message. Ready?'
9+
);
10+
11+
if (!confirmSpendingQubes) {
12+
return;
13+
}
14+
615
sessionStorage.setItem('baqupRunning', true);
716

817
function downloadJson(jsonString, label) {
@@ -32,8 +41,6 @@
3241
return;
3342
}
3443

35-
downloadJson(localStorage.getItem('vuex'), 'account');
36-
3744
function downloadTransactions(url, fileNum = 0) {
3845
let xhr = new XMLHttpRequest();
3946
xhr.open('GET', url, true);

index.html

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,70 @@
6363

6464
<h2>It's your money. It's your data.<br />Back it up!</h2>
6565

66+
<a
67+
class="bookmarklet"
68+
href="javascript: (function () {
69+
const confirmSpendingQubes = window.confirm(
70+
'Click on every Spending Qube once before continuing. Ready?'
71+
);
72+
73+
if (!confirmSpendingQubes) {
74+
alert(
75+
'Please go back and click on every spending qube before downloading your data.'
76+
);
77+
return;
78+
}
79+
80+
function downloadJson(jsonString, label) {
81+
var anchor = document.createElement('a');
82+
anchor.setAttribute(
83+
'href',
84+
'data:application/json;charset=utf-8,' + encodeURIComponent(jsonString)
85+
);
86+
var timestamp = new Date().toISOString().slice(0, 10);
87+
anchor.setAttribute('download', `baqup-${label} ${timestamp}.json`);
88+
anchor.setAttribute('target', '_blank');
89+
anchor.style.display = 'none';
90+
document.body.appendChild(anchor);
91+
92+
anchor.click();
93+
}
94+
95+
const cache = JSON.parse(localStorage.getItem('vuex'));
96+
97+
const currentURL = new URL(window.location.href);
98+
if (
99+
!cache ||
100+
currentURL.protocol !== 'https:' ||
101+
currentURL.hostname !== 'dashboard.qubemoney.com'
102+
) {
103+
alert('You must be viewing Qube and logged in to download your data.');
104+
return;
105+
}
106+
107+
downloadJson(localStorage.getItem('vuex'), 'account');
108+
})();
109+
110+
"
111+
>💾 BaQup Qubes</a
112+
>
113+
66114
<a
67115
class="bookmarklet"
68116
href="javascript: (function () {
69117
if (sessionStorage.getItem('baqupRunning')) {
70118
alert('baQup Tools is already running. Please wait for it to finish.');
71119
return;
72120
}
121+
122+
const confirmSpendingQubes = window.confirm(
123+
'This will download all your transactions as multiple files. Stay on the page until you see the completion message. Ready?'
124+
);
125+
126+
if (!confirmSpendingQubes) {
127+
return;
128+
}
129+
73130
sessionStorage.setItem('baqupRunning', true);
74131
75132
function downloadJson(jsonString, label) {
@@ -99,8 +156,6 @@ <h2>It's your money. It's your data.<br />Back it up!</h2>
99156
return;
100157
}
101158
102-
downloadJson(localStorage.getItem('vuex'), 'account');
103-
104159
function downloadTransactions(url, fileNum = 0) {
105160
let xhr = new XMLHttpRequest();
106161
xhr.open('GET', url, true);
@@ -139,7 +194,7 @@ <h2>It's your money. It's your data.<br />Back it up!</h2>
139194
);
140195
})();
141196
"
142-
>💾 BaQup My Qubes</a
197+
>💾 BaQup Transactions</a
143198
>
144199

145200
<ol>

style.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
:root {
22
--base: #fff;
3+
--zebra: #dfdfdf;
34
--inverted: #222;
45
--interactive: #5ee9ae;
56
--interactive--darker: #19b373;
@@ -58,9 +59,10 @@ a:not(.bookmarklet):hover {
5859
margin: 0 auto;
5960
border: dashed 4px var(--interactive);
6061
animation: outline-crawl 2s linear infinite;
62+
margin: 0.3em 0;
6163
}
6264
.bookmarklet:after {
63-
content: "Drag me to your bookmarks toolbar!";
65+
content: 'Drag me to your bookmarks toolbar!';
6466
display: inline-block;
6567
position: absolute;
6668
top: -1em;
@@ -96,3 +98,7 @@ a:not(.bookmarklet):hover {
9698
.fine-print {
9799
font-size: 0.75rem;
98100
}
101+
102+
.bigbreak {
103+
height: 50vh;
104+
}

visualizer.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
table {
2+
overflow-x: scroll;
3+
font-size: 0.9rem;
4+
}
5+
6+
th {
7+
position: sticky;
8+
top: 0;
9+
background-color: var(--base);
10+
border-bottom: solid 1px var(--inverted);
11+
}
12+
13+
th,
14+
td {
15+
text-align: end;
16+
padding: 0.1em 0.5em;
17+
font-family: monospace;
18+
}
19+
20+
tr:nth-child(even) {
21+
background-color: var(--zebra);
22+
}

visualizer.html

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
33
<p>A completely offline tool to view your snapshot.</p>
44
5-
<div class="dropzone">
6-
<input type="file" id="fileInput" />
7-
<label for="fileInput"> Drag and drop your backup file here. </label>
8-
</div>
5+
96
107
118
-->
@@ -58,14 +55,46 @@
5855

5956
<meta name="theme-color" content="#19b373" />
6057
<link rel="stylesheet" href="style.css" />
58+
<link rel="stylesheet" href="visualizer.css" />
6159
</head>
6260
<body>
63-
<h1>baQup Snapshot Visualizer</h1>
64-
<p>This tool isn't done yet. Come back in a day or two!</p>
61+
<div class="hero">
62+
<img src="baqup-tools-logo-optimized.svg" alt="baqup tools logo" />
63+
</div>
64+
65+
<h1>Snapshot Visualizers</h1>
66+
<p>You can use these tools to view your backups offline.</p>
67+
68+
<h2>Qubes</h2>
69+
<div class="dropzone">
70+
<input type="file" id="fileInput" />
71+
<label for="fileInput"> Drag and drop your account file here. </label>
72+
</div>
73+
74+
<table id="qubes">
75+
<thead>
76+
<tr>
77+
<th>Name</th>
78+
<th>Type</th>
79+
<th>12 Month</th>
80+
<th>6 Month</th>
81+
<th>3 Month</th>
82+
<th>Budget</th>
83+
<th>Bill/Goal</th>
84+
</tr>
85+
</thead>
86+
<tbody></tbody>
87+
</table>
88+
89+
<div class="bigbreak"></div>
90+
91+
<p>I'm working on more tools! Come back in a day or two!</p>
6592
<img
6693
src="under-construction.gif"
6794
alt="Under Construction"
6895
style="width: 100%"
6996
/>
97+
98+
<script src="visualizer.js"></script>
7099
</body>
71100
</html>

visualizer.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
document.querySelector('.dropzone').addEventListener('drop', (e) => {
2+
e.preventDefault();
3+
let file = e.dataTransfer.files[0];
4+
let reader = new FileReader();
5+
reader.onload = (event) => {
6+
let jsonData = JSON.parse(event.target.result);
7+
console.log(jsonData);
8+
const qubesTable = document.querySelector('#qubes > tbody');
9+
addQubesToTable(qubesTable, jsonData);
10+
};
11+
reader.readAsText(file);
12+
});
13+
14+
document.querySelector('input[type=file]').addEventListener('change', (e) => {
15+
let file = e.target.files[0];
16+
let reader = new FileReader();
17+
reader.onload = (event) => {
18+
let jsonData = JSON.parse(event.target.result);
19+
console.log(jsonData);
20+
const qubesTable = document.querySelector('#qubes > tbody');
21+
addQubesToTable(qubesTable, jsonData);
22+
};
23+
reader.readAsText(file);
24+
});
25+
26+
function addQubesToTable(qubesTable, jsonData) {
27+
jsonData.qubes.qubes.forEach((qube) => {
28+
const row = qubesTable.insertRow();
29+
const cells = [
30+
row.insertCell(),
31+
row.insertCell(),
32+
row.insertCell(),
33+
row.insertCell(),
34+
row.insertCell(),
35+
row.insertCell(),
36+
row.insertCell(),
37+
];
38+
cells[0].innerHTML = qube.name;
39+
cells[1].innerHTML = qube.type;
40+
switch (qube.type) {
41+
case 'billing': {
42+
cells[2].innerHTML = qube.billqube?.spend_avg_12_months;
43+
cells[3].innerHTML = qube.billqube?.spend_avg_6_months;
44+
cells[4].innerHTML = qube.billqube?.spend_avg_3_months;
45+
cells[6].innerHTML = qube.billqube.bill_amount;
46+
break;
47+
}
48+
case 'goal': {
49+
cells[2].innerHTML = qube.goalqube?.spend_avg_12_months;
50+
cells[3].innerHTML = qube.goalqube?.spend_avg_6_months;
51+
cells[4].innerHTML = qube.goalqube?.spend_avg_3_months;
52+
cells[6].innerHTML = qube.goalqube?.goal_amount;
53+
break;
54+
}
55+
case 'spending': {
56+
cells[2].innerHTML = qube.spendingqube?.spend_avg_12_months;
57+
cells[3].innerHTML = qube.spendingqube?.spend_avg_6_months;
58+
cells[4].innerHTML = qube.spendingqube?.spend_avg_3_months;
59+
cells[6].innerHTML = '-';
60+
break;
61+
}
62+
}
63+
cells[5].innerHTML = qube.budget;
64+
});
65+
}

0 commit comments

Comments
 (0)