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
2 changes: 1 addition & 1 deletion .github/workflows/badge-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
#
# -- Lint and parse Output
#
pylint_output=$(PYTHONPATH=. pylint . --recursive=y --disable=W0511,R0903 --score=y)
pylint_output=$(PYTHONPATH=. pylint . --recursive=y --score=y)
score=$(sed -n '$s/[^0-9]*\([0-9.]*\).*/\1/p' <<< "$pylint_output")

#
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ jobs:
#
# -- Lint and parse Output
#
pylint_output=$(PYTHONPATH=. pylint . --recursive=y --disable=W0511,R0903,R0801 --score=y)
pylint_output=$(PYTHONPATH=. pylint . --recursive=y --score=y)
exitcode=$?
score=$(sed -n '$s/[^0-9]*\([0-9.]*\).*/\1/p' <<< "$pylint_output")
#
Expand Down
11 changes: 10 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
[pylint]
disable=logging-fstring-interpolation, unspecified-encoding,attribute-defined-outside-init,wrong-import-position
disable=
E0401, # import-error
W0511, # fixme
W1203, # logging-fstring-interpolation
R0903, # too-few-public-methods
R0915, # too-many-statements
R0913, # too-many-arguments
R0912, # too-many-branches
R0914, # too-many-locals
R0917 # too-many-positional-arguments
24 changes: 14 additions & 10 deletions app/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,29 @@ def require_login():
"""
# Allow PyTest Client
if current_app.config.get('TESTING', False):
return
return None

# Allow access to login route
# Allow access to login route or static content needed before login
if request.endpoint == "login":
return
return None

# Allow access to CSS files
if request.endpoint == "static" and request.path.endswith(".css"):
return
if request.endpoint == "static" and (
request.path.endswith('manifest.json') or
request.path.endswith('sw.js')
):
return None

# Allow access to JS files
if request.endpoint == "static" and request.path.endswith(".js"):
return
if request.path.startswith('/static/css') or \
request.path.startswith('/static/js') or \
request.path.startswith('/static/icons'):
return None

# Block everything else unless logged in
if not session.get("logged_in"):
return redirect('/login')

return
# Return no Redirection for logged-in users
return None

@current_app.route("/login", methods=["GET", "POST"])
def login():
Expand Down
4 changes: 3 additions & 1 deletion app/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(parent_dir))
from app.ui import UserInterface

# Relative imports need to be after sys.path append
from app.ui import UserInterface #pylint: disable=wrong-import-position


def create_app(config_path: str) -> Flask:
Expand Down
4 changes: 4 additions & 0 deletions app/static/css/grid.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
"gegen-val gegen-val"
"tx-head tx-head"
"tx-val tx-val"
"txt-head txt-head"
"txt-val txt-val"
". .";
}

Expand All @@ -59,6 +61,8 @@
#dynamic-results tr:nth-child(4) td { grid-area: gegen-val;}
#dynamic-results tr:nth-child(9) th { grid-area: tx-head;}
#dynamic-results tr:nth-child(9) td { grid-area: tx-val;}
#dynamic-results tr:nth-child(10) th { grid-area: txt-head;}
#dynamic-results tr:nth-child(10) td { grid-area: txt-val;}

/* Stack nav */
nav { display: block; }
Expand Down
7 changes: 6 additions & 1 deletion app/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ small.secondary, strong.secondary, i.secondary {
.bottom-fixed > button {
border-radius: 2em;
}

#pwa-install-btn {
margin-bottom: 6em;
}

/* Info TX button */
button.info {
padding: 1em;
Expand Down Expand Up @@ -159,7 +164,6 @@ button.info {
background-color: var(--pico-code-kbd-background-color);
border-radius: var(--pico-border-radius);
color: var(--pico-code-kbd-color);
font-weight: bolder;
font-size: .875em;
font-family: var(--pico-font-family);
line-height: initial;
Expand All @@ -184,6 +188,7 @@ button.info {
}

.tag-chip.parsed {background-color: blueviolet; color:black;}
.tag-chip.parsed b {display: block;}
.tag-chip:hover { filter: brightness(110%); }

/* Generated Color Classes */
Expand Down
Binary file added app/static/icons/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/static/icons/favicon.ico
Binary file not shown.
Binary file added app/static/icons/icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/static/icons/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions app/static/js/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
let IBAN = window.location.pathname.split('/')[1];
let TAGS = [];

// ----------------------------------------------------------------------------
// -- General Listeners -------------------------------------------------------
// ----------------------------------------------------------------------------

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

// Set PWA if used in PWA
if (sessionStorage.getItem('pwa_installed') != 'true'){
if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches ||
window.navigator.standalone === true) {
sessionStorage.setItem('pwa_installed', 'true');
}
}

});

// ----------------------------------------------------------------------------
// -- DOM Functions ----------------------------------------------------------
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -393,6 +409,19 @@ function createAjax(callback) {
return ajax;
}

// -----------------------------
// PWA: Service Worker registration and Install prompt handling
// -----------------------------
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/static/sw.js').then(function (reg) {
console.log('Service worker registered.', reg);
}).catch(function (err) {
console.warn('Service worker registration failed:', err);
});
});
}

/**
* Sends a GET request to the specified API endpoint with the given parameters.
*
Expand Down
16 changes: 16 additions & 0 deletions app/static/js/iban.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ document.addEventListener('DOMContentLoaded', function () {
window.location.href = '/' + IBAN;
})

// Update Details Link ("_blank" for non-PWA)
updateDetailsLink();

});

// ----------------------------------------------------------------------------
Expand All @@ -60,6 +63,19 @@ function set_all_checkboxes() {
listTxElements();
}

/**
* Set "more" button to target "_blank" if not PWA
*/
function updateDetailsLink() {
var a = document.querySelector('#details-popup footer a.secondary');
if (!a) return;
if (sessionStorage.getItem('pwa_installed') == 'true') {
a.removeAttribute('target');
} else {
a.setAttribute('target', '_blank');
}
}

/**
* Set an eventlistener for every box and change the header when unselected
*
Expand Down
11 changes: 11 additions & 0 deletions app/static/js/tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,15 @@ function manualTagTx(uuid) {
*/
function manualCatTx(uuid) {
return manualCat([uuid], document.getElementById('cat-input').value);
}

/**
* Close window when used as PWA, otherwise go back in browser history.
*/
function closeOrBack() {
if (sessionStorage.getItem('pwa_installed') != 'true') {
window.close();
} else {
window.history.back();
}
}
21 changes: 21 additions & 0 deletions app/static/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "PynanceParser",
"short_name": "PynanceParser",
"start_url": "/",
"display": "standalone",
"background_color": "#13171f",
"theme_color": "#00b478",
"description": "Get Insides into your Bank Account",
"icons": [
{
"src": "/static/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
12 changes: 6 additions & 6 deletions app/static/sw.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
self.addEventListener('install', function (event) {
event.waitUntil(
function(){
console.log("SW: PWA installiert !");
}
);
self.skipWaiting();
});

self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim());
});

self.addEventListener('fetch', function (event) {
// Bisher kein Ressourcen Management nötig !
// Not needed for now...
});
3 changes: 3 additions & 0 deletions app/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/pico.jade.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/grid.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='icons/favicon.ico') }}">
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
<meta name="theme-color" content="#4db6ac">
</head>
<body>

Expand Down
35 changes: 35 additions & 0 deletions app/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,40 @@ <h1>Pynance Parser</h1>

</main>

<script>
let deferredPWAInstall = null;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPWAInstall = e;
let btn = document.getElementById('pwa-install-btn');
if (!btn) {
btn = document.createElement('button');
btn.id = 'pwa-install-btn';
btn.className = 'secondary';
btn.textContent = 'Install WebApp';
btn.addEventListener('click', async () => {
btn.style.display = 'none';
deferredPWAInstall.prompt();
const choice = await deferredPWAInstall.userChoice;
deferredPWAInstall = null;
if (choice.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
}
});
document.querySelector('body footer').prepend(document.createElement('br'));
document.querySelector('body footer').prepend(btn);
} else {
btn.style.display = 'inline-block';
}
});

window.addEventListener('appinstalled', (evt) => {
const btn = document.getElementById('pwa-install-btn');
if (btn) btn.style.display = 'none';
console.log('PWA was installed.');
});
</script>

{% endblock %}
2 changes: 1 addition & 1 deletion app/templates/tx.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h3>
</ul>
<ul>
<li>
<button class="secondary" onclick="window.close()">
<button class="secondary" onclick="closeOrBack()">
&times; schließen
</button>
</li>
Expand Down
4 changes: 3 additions & 1 deletion app/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)

# Relative imports need to be after sys.path append
#pylint: disable=wrong-import-position
from app.routes import Routes

from handler.TinyDb import TinyDbHandler
Expand All @@ -22,7 +24,7 @@
from reader.Comdirect import Reader as Comdirect
from reader.Commerzbank import Reader as Commerzbank
from reader.Volksbank_Mittelhessen import Reader as Volksbank_Mittelhessen

#pylint: enable=wrong-import-position

class UserInterface():
"""Basisklasse mit Methoden für den Programmablauf"""
Expand Down
2 changes: 1 addition & 1 deletion handler/BaseDb.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def delete(self, collection: str, condition: dict | list[dict]=None, multi: str=

return {'deleted': update_result}

def _delete(self, collection: str, condition: dict | list[dict], multi: str):
def _delete(self, collection: str, condition: dict | list[dict]=None, multi: str='AND'):
"""
Private Methode zum Löschen von Datensätzen in der Datenbank,
die die angegebene Bedingung erfüllen. Siehe 'delete' Methode.
Expand Down
2 changes: 1 addition & 1 deletion reader/Generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(self):
folgt dem Template in `Models.md` sofern die Felder mit den Informationen
von hier sicher gefüllt werden können.
"""
return
self.all_rows = []

def from_csv(self, filepath):
"""
Expand Down
Loading