Skip to content
Merged
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
8 changes: 4 additions & 4 deletions app/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

import os
from datetime import datetime
import secrets
from flask import request, current_app, render_template, redirect, \
make_response, send_from_directory, session
import secrets


class Routes:
Expand Down Expand Up @@ -383,12 +383,12 @@ def uploadIban(iban):
Returns:
json: Informationen zur Datei und Ergebnis der Untersuchung.
"""
input_file = request.files.get('file-input')
input_file = request.files.get('file-batch')
if not input_file:
return {'error': 'Es wurde keine Datei übermittelt.'}, 400

# Store Upload file to tmp
path = '/tmp/transactions.tmp'
path = f"/tmp/{secrets.token_hex(12)}"
content_type, size = parent.mv_fileupload(input_file, path)

# Daten einlesen und in Object speichern (Bank und Format default bzw. wird geraten)
Expand Down Expand Up @@ -416,7 +416,7 @@ def uploadIban(iban):
insert_result = parent.db_handler.insert(parsed_data, iban)
inserted = insert_result.get('inserted')

except (KeyError, ValueError, NotImplementedError) as ex:
except (KeyError, ValueError) as ex:
return {
"error": (
"Die hochgeladene Datei konnte nicht verarbeitet werden, "
Expand Down
17 changes: 14 additions & 3 deletions app/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,31 @@ button.info {
}

/* Tables */
.transactions th {
cursor: pointer;
}
.transactions .amount {
white-space: nowrap;
text-align: right;
}
.transactions th.amount {
text-align: center;
}
.transactions th.sorted-asc::after, .transactions th.sorted-desc::after {
position: absolute;
margin-left: 4px;
color: var(--pico-primary);
}
.transactions th.sorted-asc::after { content: "\2193"; }
.transactions th.sorted-desc:after { content: "\2191"; }

#dynamic-results tr th {
font-weight: bold;
}

/* S : Slim button in transaction table */
@media (max-width: 767px) {
.transactions th.amount {
text-align: center;
}

.transactions tr {
border-bottom: var(--pico-border-width) solid var(--pico-table-border-color);
}
Expand Down
150 changes: 150 additions & 0 deletions app/static/js/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,156 @@ function removeTagBullet(element, hiddenInputId) {

}


/**
* Show a popup with a result message from an operation
*
* @param {string} heading Heading for the PopUp
* @param {list} domlist List of DOMELements to add in the "content" section
*/
function responsePopUp(heading, domlist) {
const popup = document.getElementById('response-popup');
popup.querySelector('header h2').textContent = heading;

const content = document.getElementById('response-content');
content.innerHTML = '';
domlist.forEach(dom => {
content.appendChild(dom);
});

// Close actual Popup if open and open Response PopUp
const openPopUp = document.querySelector('dialog[open] header button')
if (openPopUp) {
openPopUp.click();
}
openModal(popup, { 'currentTarget': { 'dataset': {} } });
}

/** Show a popup with an error message from an operation
*
* @param {string} heading Heading for the PopUp
* @param {number} error Error code
* @param {string} responseText Response text from the operation
*/
function errorPopUp(heading, error, responseText) {
const reason1 = document.createElement('p');
reason1.innerHTML = "Fehler " + error;
reason1.className = 'error';
const reason2 = document.createElement('pre');
reason2.innerHTML = responseText;
responsePopUp(heading, [reason1, reason2]);
}

/**
* Sort Table Rows
*
* @param {string} table_id The ID of the tabel to sort rows in
*
* @param {number} col_index The index of the column to compare rows content with
*/
function sortTable(table_id, col_index){
const table = document.getElementById(table_id);
if (!table){
console.error("Table '", table_id, "' to sort was not found");
}
if (typeof col_index == 'undefined'){
col_index = 0;
}

var switching = true;
var switchcount = 0;
var dir = "asc";

while (switching) {
// Loop until nothing else was switched
switching = false;
var rows = table.rows;

/*
Loop through the actual order of rows and
compare if one pair should be switched.
Break if a pair is found and switch it later.
This loop will be started again after the switch.
*/
for (var i = 1; i < (rows.length - 1); i++) {
var should_switch = false;
var x = rows[i].getElementsByTagName('td')[col_index];
var y = rows[i + 1].getElementsByTagName('td')[col_index];

// Compare values with special handling for numbers
if (col_index == 0) {
// Compare timestamp from dataset
var x_val = Number(x.getElementsByTagName('input')[0].dataset.txdate);
var y_val = Number(y.getElementsByTagName('input')[0].dataset.txdate);

} else if (col_index == 5){
// Compare amount (numbers)
var x_val = Number(x.innerText.slice(0, -4));
var y_val = Number(y.innerText.slice(0, -4));

} else {
// Compare normal innerText
var x_val = x.innerText.toLowerCase();
var y_val = y.innerText.toLowerCase();
}

// Compare (depending on direction)
if (dir == "asc"){

if (x_val > y_val) {
// Switch needed: Brake!
should_switch = true;
break;
}

} else if (dir == "desc") {

if (x_val < y_val) {
// Switch needed: Brake!
should_switch = true;
break;
}

}
}

// Was a needed switch found in the loop?
if (should_switch) {
// Yes: Switch it now
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);

// Remember that we at least switched one time
switchcount ++;

// Reset switching-var to get into the next iteration of the while loop
switching = true;

} else {
// There is no need for a switch...
if (switchcount == 0 && dir == "asc") {
// ...and there weren't any switches before:
// Change the direction of the sorting if it is still default 'asc'
dir = "desc";

// Reset switching-var to get into the next iteration of the while loop
switching = true;
}
}

}

const table_headings = rows[0].getElementsByTagName('th');
for (var i=0; i < table_headings.length; i++){
table_headings[i].classList.remove('sorted-asc');
table_headings[i].classList.remove('sorted-desc');
}
if (col_index == 0){
table_headings[1].classList.add('sorted-' + dir);
} else {
table_headings[col_index].classList.add('sorted-' + dir);
}
}

// ----------------------------------------------------------------------------
// -- AJAX Functions ----------------------------------------------------------
// ----------------------------------------------------------------------------
Expand Down
57 changes: 37 additions & 20 deletions app/static/js/iban.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,26 +228,41 @@ function tagAndCat(operation) {
}

apiSubmit(api_url + IBAN, payload, function (responseText, error) {
const heading = operation == 'tag' ? 'Tagging' : 'Kategorisierung';
if (error) {
alert(operation + ' failed: ' + '(' + error + ')' + responseText);
errorPopUp(
operation.substring(1) + operation.substring(0, 1).toUpperCase() + ' fehlgeschlagen',
error, responseText
);

} else {
alert(operation + ' successful!' + responseText);
if (dry_run) {
// List UUIDs which would have been tagged/cat
const r = JSON.parse(responseText)
let txt_list = ""
r.entries.forEach(element => {
txt_list += "\n- " + element
});
alert("Folgende UUIDs würden geändert werden:\n" + txt_list);
const reason1 = document.createElement('p');
reason1.innerHTML = dry_run ? "Folgende Transaktionen wären geändert worden:" : "Folgende Transaktionen wurden geändert:";

} else {
// Tagged/Cat -> Reload
window.location.reload();
const reason2 = document.createElement('ul');
let r = JSON.parse(responseText)

if (r.entries.length == 0) {
const li = document.createElement('li');
li.innerHTML = '(keine)';
reason2.appendChild(li);
}

r.entries.forEach(element => {
let li = document.createElement('li');
let a = document.createElement('a');
a.href = '/' + IBAN + '/' + element;
a.target = '_blank';
a.innerHTML = element;
li.appendChild(a);
reason2.appendChild(li);
});

responsePopUp(
heading + ' erfolgreich',
[reason1, reason2]);
}

}, false);
}

Expand All @@ -270,11 +285,12 @@ function removeTags() {

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

} else {
alert('Entries tags deleted successfully!' + responseText);
window.location.reload();
const p = document.createElement('p');
p.innerHTML = 'Die Tags der ausgewählten Einträge wurden erfolgreich entfernt.';
responsePopUp('Tags entfernt', [p]);

}
}, false);
Expand All @@ -300,11 +316,12 @@ function removeCats() {

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

} else {
alert('Entries category deleted successfully!' + responseText);
window.location.reload();
const p = document.createElement('p');
p.innerHTML = 'Die Kategorie der ausgewählten Einträge wurden erfolgreich entfernt.';
responsePopUp('Kategorie entfernt', [p]);

}
}, false);
Expand Down Expand Up @@ -344,7 +361,7 @@ function addCat() {
function getInfo(uuid, callback = alert) {
apiGet('/' + IBAN + '/' + uuid, {}, function (responseText, error) {
if (error) {
alert('getTx failed: ' + '(' + error + ')' + responseText);
errorPopUp('Transaktionsabruf fehlgeschlagen', error, responseText);

} else {
callback(responseText);
Expand Down
Loading