Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,3 @@
# For tiny: Filename ('testdata.json')
# For mongo: Collection name ('testdata')
DATABASE_NAME = 'testdata.json'

IBAN = 'DE89370400440532013000'
2 changes: 1 addition & 1 deletion app/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ def create_app(config_path: str) -> Flask:
'config.py'
)
application = create_app(config)
application.run(host='0.0.0.0', port=8110)
application.run(host='0.0.0.0', port=8110, debug=True)
23 changes: 22 additions & 1 deletion app/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@ html, body {
background-color: silver;
}

.popup {
border: 1px solid silver;
display: inline-block;
}

#file-drop-area {
border: 2px dashed #ccc;
padding: 20px;
text-align: center;
cursor: pointer;
position: relative;
}

#result-text {
display: block;
background-color: silver;
background-color: green;
padding: 1em;
margin: 1em;
}
Expand All @@ -36,3 +49,11 @@ table.transactions {
table.transactions tr:hover {
background-color: #374d3a;
}

.tag-chip {
margin-right: 0.2em;
padding: 0.2em;
background-color: #4ab477;
color: black;
border-radius: 0.2em;
}
24 changes: 24 additions & 0 deletions app/static/js/functions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
"use strict";

// ----------------------------------------------------------------------------
// -- DOM Functions ----------------------------------------------------------
// ----------------------------------------------------------------------------


/**
* Opens a popup to display details
*
* @param {string} id - The ID of the HTML element to display as a popup.
*/
function openPopup(id) {
document.getElementById(id).style.display = 'block';
}

/**
* Closes a popup by setting its display style to 'none'.
*
* @param {string} popupId - The ID of the popup element to be closed.
*/
function closePopup(popupId) {
document.getElementById(popupId).style.display = 'none';
}


// ----------------------------------------------------------------------------
// -- AJAX Functions ----------------------------------------------------------
// ----------------------------------------------------------------------------
Expand Down
300 changes: 300 additions & 0 deletions app/static/js/iban.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
"use strict";

let rowCheckboxes = null;
let IBAN = window.location.pathname.split('/').pop();

document.addEventListener('DOMContentLoaded', function () {

// PopUps
document.getElementById('settings-button').addEventListener('click', function () {
openPopup('settings-popup');
});

// enabling/disabling the edit button based on checkbox selection
const selectAllCheckbox = document.getElementById('select-all');
rowCheckboxes = document.querySelectorAll('.row-checkbox');

selectAllCheckbox.addEventListener('change', function () {
rowCheckboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
updateEditButtonState();
listTxElements();
});

rowCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function () {
if (!this.checked) {
selectAllCheckbox.checked = false;
} else if (Array.from(rowCheckboxes).every(cb => cb.checked)) {
selectAllCheckbox.checked = true;
}
updateEditButtonState();
listTxElements();
});
});

});

// ----------------------------------------------------------------------------
// -- DOM Functions -----------------------------------------------------------
// ----------------------------------------------------------------------------

/**
* Opens a popup to display details for a specific element and optionally fetches transaction details.
*
* @param {string} id - The ID of the HTML element to display as a popup.
* @param {string|null} [tx_hash=null] - Optional transaction hash to fetch additional details for.
*/
function openDetailsPopup(id, tx_hash = null) {
if (tx_hash) {
// Use AJAX to fetch and populate details for the transaction with the given ID
console.log(`Fetching details for transaction hash: ${tx_hash}`);
resetDetails();
getInfo(tx_hash, fillTxDetails);
openPopup(id);

} else {
openPopup(id);

}
}


/**
* Clears information from a result Box
*
*/
function resetDetails() {
const box = document.getElementById('result-text');
box.innerHTML = "";
}


/**
* Shows a given Result in the Result-Box.
*
* @param {string} result - The text to be shwon.
*/
function fillTxDetails(result){
const box = document.getElementById('result-text');
box.innerHTML = result;
}

/**
* Updates the state of the "Edit Selected" button based on the checkbox selections.
*
* This function checks if any row checkboxes are selected and enables or disables
* the "Edit Selected" button accordingly. It also updates the button's title to
* reflect the number of selected checkboxes.
*
* Assumes that `rowCheckboxes` is a collection of checkbox elements and that
* there is a button with the ID `edit-selected` in the DOM.
*/
function updateEditButtonState() {
const anyChecked = Array.from(rowCheckboxes).some(cb => cb.checked);
const editButton = document.getElementById('edit-selected');
editButton.disabled = !anyChecked;
editButton.title = anyChecked
? `Edit (${Array.from(rowCheckboxes).filter(cb => cb.checked).length} selected)`
: 'Edit (nichts ausgewählt)';
}

function listTxElements() {
const result_list = document.getElementById('tx-select-list');
result_list.innerHTML = ''; // Clear the list before adding new items
rowCheckboxes.forEach(checkbox => {
if (checkbox.checked) {
const li = document.createElement('li');
li.textContent = checkbox.dataset.tx;
result_list.appendChild(li);
}
});
}

/**
* Tags the entries in the database.
* Optional Tagging commands are read from the input with ID
* 'input_tagging_name' (more in the Future)
*/
function tagEntries() {
let payload = {};
const rule_name = document.getElementById('tag-select').value;
if (rule_name) {
payload['rule_name'] = rule_name;
}
const dry_run = document.getElementById('tag-dry').checked;
if (dry_run) {
payload['dry_run'] = dry_run;
}

apiSubmit('tag/'+IBAN, payload, function (responseText, error) {
if (error) {
printResult('Tagging failed: ' + '(' + error + ')' + responseText);

} else {
alert('Entries tagged successfully!' + responseText);
window.location.reload();

}
}, false);
}

/**
* Categorize the entries in the database.
* Optional Categorization commands are read from the input with ID
*/
function catEntries() {
let payload = {};
const rule_name = document.getElementById('cat-select').value;
if (rule_name) {
payload['rule_name'] = rule_name
}
const dry_run = document.getElementById('cat-dry').checked;
if (dry_run) {
payload['dry_run'] = dry_run;
}

apiSubmit('cat/'+IBAN, payload, function (responseText, error) {
if (error) {
printResult('Categorization failed: ' + '(' + error + ')' + responseText);

} else {
alert('Entries categorized successfully!' + responseText);
window.location.reload();

}
}, false);
}

/**
* Clear Tags from selected transactions
*/
function removeTags() {
const t_ids = Array.from(rowCheckboxes)
.filter(cb => cb.checked)
.map(cb => cb.getAttribute('name'));

let api_function;
let tags = {};
if (t_ids.length == 1) {
api_function = 'removeTag/'+IBAN+'/'+t_ids[0];
} else {
api_function = 'removeTags/'+IBAN;
tags['t_ids'] = t_ids;
};

apiSubmit(api_function, tags, function (responseText, error) {
if (error) {
alert('Tag removal failed: ' + '(' + error + ')' + responseText);

} else {
alert('Entries tags deleted successfully!' + responseText);
window.location.reload();

}
}, false);
}


/**
* Clear Category from selected transactions
*/
function removeCats() {
const t_ids = Array.from(rowCheckboxes)
.filter(cb => cb.checked)
.map(cb => cb.getAttribute('name'));

let api_function;
let payload = {};
if (t_ids.length == 1) {
api_function = 'removeCat/'+IBAN+'/'+t_ids[0];
} else {
api_function = 'removeCats/'+IBAN;
payload['t_ids'] = t_ids;
};

apiSubmit(api_function, payload, function (responseText, error) {
if (error) {
alert('Cat removal failed: ' + '(' + error + ')' + responseText);

} else {
alert('Entries category deleted successfully!' + responseText);
window.location.reload();

}
}, false);
}


/**
* Tags the entries in the database in a direct manner
* A single or multiple transactions to tag must be selected wit checkboxes.
*/
function manualTagEntries() {
let tags = document.getElementById('manual-tag-input').value;
let tagging = {
'tags': tags
}

const t_ids = Array.from(rowCheckboxes).filter(cb => cb.checked)

let api_function;
if (t_ids.length == 1) {
api_function = 'setManualTag/'+ IBAN + '/' + t_ids[0];
} else {
api_function = 'setManualTags/' + IBAN;
tagging['t_ids'] = t_ids;
};

apiSubmit(api_function, tagging, function (responseText, error) {
if (error) {
printResult('Tagging failed: ' + '(' + error + ')' + responseText);

} else {
alert('Entries tagged successfully!' + responseText);
window.location.reload();

}
}, false);
}


/**
* Fetches information based on the provided IBAN and UUID, and processes the response.
*
* @param {string} uuid - The unique identifier associated with the request.
* @param {Function} [callback=alert] - A callback function to handle the response text. Defaults to `alert`.
*/
function getInfo(uuid, callback = alert) {
apiGet('/' + IBAN + '/' + uuid, {}, function (responseText, error) {
if (error) {
printResult('getTx failed: ' + '(' + error + ')' + responseText);

} else {
callback(responseText);

}
});
}


function saveMeta() {
const meta_type = document.getElementById('select_meta').value;
const fileInput = document.getElementById('input-json');
if (fileInput.files.length === 0) {
alert('Please select a file to upload.');
return;
}

const params = { file: 'input_file' }; // The key 'file' corresponds to the input element's ID
apiSubmit('upload/metadata/'+meta_type, params, function (responseText, error) {
if (error) {
printResult('Rule saving failed: ' + '(' + error + ')' + responseText);

} else {
alert('Rule saved successfully!' + responseText);

}
}, true);
}
Loading
Loading