259 lines
8.4 KiB
JavaScript
259 lines
8.4 KiB
JavaScript
var gui = require('gui');
|
|
var fs = require('fs');
|
|
const { waitForAddAccountWindow } = require('./waitForAddAccountWindow');
|
|
const { waitForDataEntryWindow } = require('./waitForDataEntryWindow');
|
|
const { waitForCloseAccountWindow } = require('./waitForCloseAccountWindow');
|
|
const { getAccounts, toListViewEntries, getSummation } = require('./utils');
|
|
const { waitForChartWindow } = require('./waitForChartWindow');
|
|
|
|
function mainWindow(projectData) {
|
|
|
|
var rh = 14;
|
|
var sp = 4;
|
|
var y = sp;
|
|
|
|
let internalProjectData = projectData;
|
|
|
|
let invalidate = false;
|
|
|
|
let gadgets = [];
|
|
|
|
const cycleId = 1;
|
|
const listViewId = 2;
|
|
const balanceId = 3;
|
|
const addButtonId = 4;
|
|
|
|
cols = 56;
|
|
|
|
gadgets.push({
|
|
kind: 'cycle', id: cycleId,
|
|
left: sp, top: y, width: 120, height: rh, border: false,
|
|
items: getAccounts(internalProjectData), value: 0
|
|
});
|
|
|
|
gadgets.push({
|
|
kind: 'button', id: addButtonId,
|
|
left: -(sp + 80),
|
|
top: y,
|
|
width: 80,
|
|
label: "+Transfer",
|
|
height: rh
|
|
});
|
|
|
|
gadgets.push({
|
|
kind: 'listview', id: listViewId,
|
|
left: sp,
|
|
top: y + rh + sp,
|
|
width: 500 - sp - sp,
|
|
height: 186,
|
|
items: toListViewEntries(internalProjectData[0].entries, cols),
|
|
value: 0
|
|
});
|
|
|
|
gadgets.push({
|
|
kind: 'text', id: balanceId,
|
|
label: 'Balance:',
|
|
left: 100,
|
|
top: -(sp + rh),
|
|
width: 400 - sp,
|
|
height: rh,
|
|
value: getSummation(internalProjectData[0].entries).toFixed(2)
|
|
});
|
|
|
|
let win = gui.createWindow({
|
|
title: 'Budget',
|
|
width: 500,
|
|
height: 14 + 4 + 4 + 200 + 4,
|
|
left: 20,
|
|
top: 15,
|
|
gadgets: gadgets,
|
|
});
|
|
|
|
/* Set up menu bar */
|
|
gui.setMenu(win, [
|
|
{
|
|
title: 'Project',
|
|
items: [
|
|
{ label: 'New', id: 101, key: 'N' },
|
|
{ label: 'Open...', id: 102, key: 'O' },
|
|
{ label: 'Save...', id: 103, key: 'S' },
|
|
{ label: '---' },
|
|
{ label: 'Quit', id: 199, key: 'Q' }
|
|
]
|
|
},
|
|
{
|
|
title: 'Accounts',
|
|
items: [
|
|
{ label: "Add...", id: 104, key: 'A' },
|
|
{ label: "Close...", id: 105, key: 'C' }
|
|
]
|
|
},
|
|
{
|
|
title: 'Charts',
|
|
items: [
|
|
{ label: "---" },
|
|
{ label: "New", id: 106 }
|
|
]
|
|
}
|
|
]);
|
|
|
|
let currentAccountIndex = 0;
|
|
|
|
let updateView = (accountIndex, data) => {
|
|
if (accountIndex != null) {
|
|
gui.set(win, cycleId, getAccounts(data));
|
|
gui.set(win, cycleId, accountIndex);
|
|
} else {
|
|
accountIndex = gui.get(win, cycleId);
|
|
}
|
|
// sort
|
|
data[accountIndex].entries = data[accountIndex].entries.sort((a, b) => a.date - b.date);
|
|
gui.set(win, 2, toListViewEntries(data[accountIndex].entries, cols));
|
|
gui.set(win, 3, getSummation(data[accountIndex].entries).toFixed(2));
|
|
}
|
|
|
|
let doNew = () => {
|
|
return [
|
|
{
|
|
name: "Current",
|
|
entries: []
|
|
}
|
|
];
|
|
}
|
|
|
|
let doOpen = () => {
|
|
var r = gui.fileRequest({ title: 'Open File', pattern: '#?.json' });
|
|
if (r) {
|
|
return JSON.parse(fs.readFileSync(r.file));
|
|
}
|
|
}
|
|
|
|
let doSave = () => {
|
|
var r = gui.fileRequest({ title: 'Save File', pattern: '#?.json', save: true });
|
|
if (r) {
|
|
fs.writeFileSync(r.file, JSON.stringify(internalProjectData));
|
|
}
|
|
}
|
|
|
|
gui.setMenuItem(win, 105, { disabled: internalProjectData.length <= 1 });
|
|
|
|
|
|
while (!invalidate) {
|
|
var evt = gui.waitEvent(win);
|
|
if (!evt) continue;
|
|
|
|
if (evt.type === 'close') {
|
|
invalidate = true;
|
|
internalProjectData = null;
|
|
}
|
|
|
|
if (evt.type === 'menu') {
|
|
if (evt.id === 101) {
|
|
internalProjectData = doNew();
|
|
updateView(0, internalProjectData);
|
|
}
|
|
else if (evt.id === 102) {
|
|
internalProjectData = doOpen();
|
|
updateView(0, internalProjectData);
|
|
}
|
|
else if (evt.id === 103) {
|
|
doSave();
|
|
}
|
|
else if (evt.id === 104) {
|
|
let indexOfNewAccount = waitForAddAccountWindow(internalProjectData);
|
|
if (indexOfNewAccount > -1) {
|
|
currentAccountIndex = indexOfNewAccount;
|
|
}
|
|
updateView(currentAccountIndex, internalProjectData);
|
|
}
|
|
else if (evt.id === 105) {
|
|
if (internalProjectData.length > 1) {
|
|
const rValue = waitForCloseAccountWindow(internalProjectData, internalProjectData[currentAccountIndex]);
|
|
if (rValue === -1) {
|
|
internalProjectData.splice(currentAccountIndex, 1);
|
|
updateView(0, internalProjectData);
|
|
}
|
|
} else {
|
|
gui.alert("Cannot close last remaining Account");
|
|
}
|
|
}
|
|
else if (evt.id === 106) {
|
|
waitForChartWindow(projectData[currentAccountIndex]);
|
|
}
|
|
else if (evt.id === 199) {
|
|
invalidate = true;
|
|
internalProjectData = null;
|
|
}
|
|
}
|
|
|
|
if (evt.type === 'gadgetup') {
|
|
|
|
if (evt.id === cycleId) {
|
|
currentAccountIndex = evt.code;
|
|
updateView(null, internalProjectData);
|
|
} else if (evt.id === listViewId) {
|
|
let selectedEntry = evt.code;
|
|
const entry = waitForDataEntryWindow(internalProjectData[currentAccountIndex].entries[evt.code], internalProjectData);
|
|
if (entry != null) {
|
|
console.log(entry);
|
|
if (entry === -1) {
|
|
console.log(selectedEntry);
|
|
internalProjectData[currentAccountIndex].entries.splice(selectedEntry, 1);
|
|
} else {
|
|
internalProjectData[currentAccountIndex].entries[selectedEntry] = entry;
|
|
}
|
|
if (entry.targetAccount) {
|
|
const targetAccount = internalProjectData.find(d => d.name === entry.targetAccount);
|
|
if (targetAccount) {
|
|
targetAccount.entries.push({
|
|
date: entry.date,
|
|
subject: "(" + internalProjectData[currentAccountIndex].name + ")" + entry.subject,
|
|
amount: -entry.amount
|
|
});
|
|
}
|
|
}
|
|
|
|
updateView(currentAccountIndex, internalProjectData);
|
|
}
|
|
} else if (evt.id === addButtonId) {
|
|
const entry = waitForDataEntryWindow(null, internalProjectData);
|
|
if (entry != null) {
|
|
internalProjectData[currentAccountIndex].entries.push(entry);
|
|
|
|
if (entry.targetAccount) {
|
|
const targetAccount = internalProjectData.find(d => d.name === entry.targetAccount);
|
|
if (targetAccount) {
|
|
targetAccount.entries.push({
|
|
date: entry.date,
|
|
subject: "(" + internalProjectData[currentAccountIndex].name + ")" + entry.subject,
|
|
amount: -entry.amount
|
|
});
|
|
}
|
|
}
|
|
updateView(currentAccountIndex, internalProjectData);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
gui.closeWindow(win);
|
|
}
|
|
|
|
|
|
let projectData = [
|
|
{ "name": "Current", "entries": [
|
|
{ "date": 1704067200000, "subject": "Salary", "amount": 2182.15000000000009 },
|
|
{ "date": 1704153600000, "subject": "(Savings) Initial Deposit", "targetAccount": "Current", "amount": -500 },
|
|
{ "date": 1704240000000, "subject": "Rent", "amount": -800 },
|
|
{ "date": 1704326400000, "subject": "Groceries", "amount": -24.19 }]
|
|
},
|
|
{ "name": "Savings", "entries": [
|
|
{ "date": 1704153600000, "subject": "Initial Deposit", "amount": 500 }]
|
|
}
|
|
];
|
|
|
|
exports.projectData = projectData;
|
|
|
|
|
|
mainWindow(projectData); |