34 Commits
0.2.6 ... 0.3.0

Author SHA1 Message Date
807f1de774 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-02-01 17:41:56 +01:00
677874a0e1 left version
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:35:41 +01:00
81fc7ade5f test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:34:28 +01:00
b941819b73 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:27:43 +01:00
dcc1336d62 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:22:08 +01:00
99bd1841cb try
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:21:30 +01:00
16f8c23c38 round
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:11:43 +01:00
cb84e3cdc0 table consistant
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:06:30 +01:00
ca734fda32 version left
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 17:03:29 +01:00
4f6d3de79c search
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 16:57:01 +01:00
bf245e215a fix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 16:49:50 +01:00
443eb9ef00 fix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 16:48:54 +01:00
ce38d6cf24 delete in db
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-02-01 16:43:31 +01:00
5c8f057843 button color
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 16:34:54 +01:00
85afd501ce version id, 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-02-01 09:55:40 +01:00
4dbc156439 version id
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 09:48:54 +01:00
fd3e8751fe order by name
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-02-01 09:28:26 +01:00
21ea1aa56f Merge branch 'main' of gitea.hottis.de:moerp/elo-rezept-rechner
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 16:46:36 +01:00
eefc8d5b21 fix image tag 2024-01-31 16:46:31 +01:00
41010b8a7b small fix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 16:27:17 +01:00
43583fb7f3 color
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 16:17:37 +01:00
1f5b4163e7 fix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 16:11:17 +01:00
38d3381ecd test instance
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 15:51:31 +01:00
db769ca053 postfix instead of prefix, 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 15:31:03 +01:00
536e933fef postfix instead of prefix 2024-01-31 15:30:53 +01:00
d469a7cf2c test deployment
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 15:27:22 +01:00
d308fd662a logging, 4
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 15:05:58 +01:00
a9a8a36cb9 logging, 3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 14:53:04 +01:00
845e4ec673 logging, 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 14:46:18 +01:00
d82770158c logging
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 13:49:14 +01:00
3852d78725 table adjusted
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 13:43:21 +01:00
fd057e3415 token stuff, 4
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 13:15:03 +01:00
e4fe5b9831 token stuff, 3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 13:09:26 +01:00
6a9b938ab9 token stuff, 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-01-31 13:03:04 +01:00
13 changed files with 246 additions and 103 deletions

View File

@ -10,10 +10,29 @@ steps:
from_secret: container_registry_username
password:
from_secret: container_registry_password
build_args:
- VERSION_ID1=${CI_COMMIT_SHA}
- VERSION_ID2=${CI_COMMIT_TAG}
dockerfile: Dockerfile
when:
- event: [push, tag]
deploytest:
image: portainer/kubectl-shell:latest
secrets:
- source: kube_config
target: KUBE_CONFIG_CONTENT
- source: encryption_key
target: ENCRYPTION_KEY
- source: secrets_checksum
target: MD5_CHECKSUM
commands:
- printf "$KUBE_CONFIG_CONTENT" > /tmp/kubeconfig
- export KUBECONFIG=/tmp/kubeconfig
- ./deployment/deploy.sh test
when:
- event: [push, tag]
deploy:
image: portainer/kubectl-shell:latest
secrets:

View File

@ -1,6 +1,8 @@
FROM python:3.12-alpine3.19
ARG APP_DIR="/opt/app"
ARG VERSION_ID1="x"
ARG VERSION_ID2="alpha"
COPY ./src/ ${APP_DIR}/
COPY start.sh ${APP_DIR}/
@ -9,7 +11,10 @@ WORKDIR ${APP_DIR}
RUN \
apk add --no-cache build-base libpq-dev && \
pip install -r requirements.txt
pip install -r requirements.txt && \
if [ "${VERSION_ID2}" != "" ]; then VERSION_ID=${VERSION_ID2}; else VERSION_ID=${VERSION_ID1}; fi && \
sed -i -e 's/VERSION_ID/'$VERSION_ID'/' ${APP_DIR}/templates/index.html && \
sed -i -e 's/VERSION_ID/'"$VERSION_ID"'/' ${APP_DIR}/templates/nutrition.html
EXPOSE 8080

View File

@ -1,5 +1,7 @@
#!/bin/bash
if [ "$ENCRYPTION_KEY" = "" ]; then
echo "ENCRYPTION_KEY not set"
exit 1
@ -10,6 +12,7 @@ if [ "$MD5_CHECKSUM" = "" ]; then
exit 1
fi
SECRETS_CIPHERTEXT_FILE=secrets.enc
SECRETS_PLAINTEXT_FILE=/tmp/secrets
TMP_FILE=`mktemp`

View File

@ -46,10 +46,10 @@ metadata:
spec:
tls:
- hosts:
- nutri.hottis.de
- nutri%POSTFIX%.hottis.de
secretName: nutri-cert
rules:
- host: nutri.hottis.de
- host: nutri%POSTFIX%.hottis.de
http:
paths:
- path: /

View File

@ -1,13 +1,19 @@
#!/bin/bash
if [ "$1" == "test" ]; then
POSTFIX="-test"
IMAGE_TAG=${CI_COMMIT_SHA}
else
POSTFIX=""
fi
if [ "$IMAGE_TAG" == "" ]; then
echo "Make sure IMAGE_TAG is set"
exit 1
fi
IMAGE_NAME=gitea.hottis.de/moerp/elo-rezept-rechner
NAMESPACE=moerp
NAMESPACE=moerp${POSTFIX}
DEPLOYMENT_DIR=$PWD/deployment
pushd $DEPLOYMENT_DIR > /dev/null
@ -15,7 +21,7 @@ pushd $DEPLOYMENT_DIR > /dev/null
. /tmp/secrets
rm /tmp/secrets
CLIENT_SECRETS=`cat oidc-config.json | sed -e's!%CLIENT_SECRET%!'$CLIENT_SECRET'!'`
CLIENT_SECRETS=`cat oidc-config${POSTFIX}.json | sed -e's!%CLIENT_SECRET%!'$CLIENT_SECRET'!'`
kubectl create namespace $NAMESPACE \
--dry-run=client \
@ -37,6 +43,7 @@ kubectl create secret generic nutri-secrets \
cat $DEPLOYMENT_DIR/deploy-yml.tmpl | \
sed -e 's,%IMAGE%,'$IMAGE_NAME':'$IMAGE_TAG','g | \
sed -e 's,%POSTFIX%,'$POSTFIX','g | \
kubectl apply -f - -n $NAMESPACE
popd > /dev/null

View File

@ -0,0 +1,13 @@
{
"web": {
"issuer": "https://auth2.hottis.de/realms/hottis",
"auth_uri": "https://auth2.hottis.de/ealms/hottis/protocol/openid-connect/auth",
"client_id": "nutri",
"client_secret": "%CLIENT_SECRET%",
"redirect_uris": [
"https://nutri-test.hottis.de/*"
],
"userinfo_uri": "https://auth2.hottis.de/realms/hottis/protocol/openid-connect/userinfo",
"token_uri": "https://auth2.hottis.de/realms/hottis/protocol/openid-connect/token"
}
}

View File

@ -5,6 +5,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
import os
import json
import psycopg2
import logging
app = Flask(__name__)
app.config.update({
@ -18,8 +19,7 @@ app.config.update({
})
oidc = OpenIDConnect(app)
app.logger.handlers = logging.getLogger('gunicorn.error').handlers
def calculate_nutrition(food, weight):
try:
@ -65,7 +65,7 @@ def get_products():
try:
conn = psycopg2.connect()
with conn.cursor() as cursor:
cursor.execute('SELECT name FROM nutrition_table')
cursor.execute('SELECT name FROM nutrition_table ORDER BY name')
products = cursor.fetchall()
return {'products': [product[0] for product in products]}
finally:
@ -105,8 +105,10 @@ def convert_decimal(value):
@app.route('/add_nutrition', methods=['POST'])
@oidc.accept_token(require_token=True, scopes_required=['openid'])
@oidc.accept_token(['openid'])
def add_nutrition():
app.logger.info("add_nutrition")
food = request.form.get('food')
kcal = convert_decimal(request.form.get('kcal'))
ew = convert_decimal(request.form.get('ew'))
@ -121,9 +123,12 @@ def add_nutrition():
with conn.cursor() as cursor:
cursor.execute("INSERT INTO nutrition_table (name, kcal, ew, fett, kh, bst, ca) VALUES (%s, %s, %s, %s, %s, %s, %s)",
(food, kcal, ew, fett, kh, bst, ca))
conn.commit()
return redirect(url_for('nutrition'))
except Exception as e:
app.logger.warn(f"error in add_nutrition: {e}")
return jsonify({"error": str(e)}), 500
finally:
if conn:
conn.close()
@ -141,13 +146,14 @@ def get_token():
@app.route('/get_database_entries')
@oidc.require_login
def get_database_entries():
try:
# Ersetzen Sie diese Werte mit Ihren Datenbank-Verbindungsinformationen
conn = psycopg2.connect()
cursor = conn.cursor()
with conn.cursor() as cursor:
cursor.execute("SELECT name, kcal, ew, fett, kh, bst, ca FROM nutrition_table")
cursor.execute("SELECT name, kcal, ew, fett, kh, bst, ca FROM nutrition_table ORDER BY name")
entries = cursor.fetchall()
# Umwandeln der Daten in ein JSON-freundliches Format
@ -169,8 +175,30 @@ def get_database_entries():
if conn:
conn.close()
app = ProxyFix(app, x_for=1, x_host=1)
@app.route('/delete_nutrition', methods=['POST'])
@oidc.accept_token(['openid'])
def delete_nutrition():
data = request.get_json()
foodNames = data['foodNames']
if not foodNames:
return jsonify({'error': 'Keine Lebensmittel zum Löschen angegeben'}), 400
try:
conn = psycopg2.connect()
with conn.cursor() as cursor:
query = "DELETE FROM nutrition_table WHERE name = ANY(%s)"
cursor.execute(query, (foodNames,))
conn.commit()
return jsonify({'message': 'Erfolgreich gelöscht'}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
finally:
if conn:
conn.close()
exposed_app = ProxyFix(app, x_for=1, x_host=1)

View File

@ -13,13 +13,16 @@ cursor = conn.cursor()
# Erstellen der Tabelle (falls noch nicht vorhanden)
cursor.execute('''
CREATE TABLE IF NOT EXISTS nutrition_table (
name TEXT,
id serial not null,
name TEXT not null,
kcal REAL,
EW REAL,
Fett REAL,
KH REAL,
BST REAL,
Ca REAL
Ca REAL,
constraint nutrition_table_pk primary key (id),
constraint nutrition_table_name_uk unique (name)
)
''')

View File

@ -6,7 +6,6 @@ Hühnerei,137,11.9,9.3,1.5,0.0,51
Pflanzenmargarine,722,0.2,80.0,0.4,0.0,8
Sahne 30%,309,2.4,31.7,3.4,0.0,80
Maisstärke,353,0.4,0.1,85.9,1.0,0
Paniermehl,368,10.1,2.1,73.5,5.3,50
Weizengrieß,335,9.6,0.8,69.0,7.1,17
Mehl405,343,9.8,1.0,71.8,4.0,15
Rapsöl,884,0,100.0,0,0,0
@ -43,13 +42,11 @@ Knoblauch,145,6.1,0.1,28.4,1.8,38
Senf,88,6.0,4.0,6.0,1.0,124
Blattspinat roh,21,2.7,0.3,0.6,2.6,117
Buttermilch,37,3.5,0.5,4.0,0.0,109
Himbeere,37,1.3,0.3,4.8,4.7,40
Salz dill gurken,9,0.4,0.1,1.3,0.5,18
Schmand 20%,205,2.8,20.0,3.6,0.0,100
Aspikpulver,338,84.2,0.1,0.0,0.0,11
Lachs atlantischer,210,20.4,13.4,0.3,0.0,4
Pinienkerne,589,24.0,50.7,7.3,7.2,26
Zwieback,385,9.9,4.3,73.1,5.2,42
Speisequark,72,13.5,0.3,3.2,0.0,92
Basilikum,47,3.1,0.8,5.1,3.1,369
Mayonaise 50%,490,0.5,52.0,5.0,0.0,10
@ -83,7 +80,6 @@ Naturreis,349,7.2,2.2,74.1,2.2,16
Mehl Type 405,343,9.8,1.0,71.8,4.0,15
Mehl Type 550,346,9.8,1.1,72.0,4.3,17
Milchreis,316,6.4,0.8,80.2,1.1,6
Kartoffelstärke,341,0.6,0.1,83.1,0.1,35
Hmilch fettarm 1.5%,47,3.4,1.5,4.9,0.0,123
Edamer 30%,254,26.4,16.2,0,0.0,800
Gouda alt 48%,414,24.6,33.7,0.1,0.0,871
@ -98,7 +94,6 @@ Butterkeks,441,8.2,11.0,74.7,3.3,47
Zwieback,385,9.9,4.3,73.1,5.2,42
Schokolade 75% Kakaomasse,598,7.8,42.6,35.0,10.9,73
Paniermehl,368,10.1,0.1,73.5,5.3,50
Senf,88,6.0,4.0,6.0,1.0,124
Schinken geräuchert,152,20.7,7.7,0.0,0.0,2
Rinderkeule,148,20.0,7.6,0.0,0.0,6
Kirsche süß,62,0.9,0.3,13.3,1.3,17
@ -107,7 +102,6 @@ Eisbergsalat,16,1.0,0.2,2.0,1.1,19
Endivie,18,1.8,0.2,1.2,1.9,54
Feldsalat,18,1.8,0.4,0.8,1.5,32
Gurke,14,0.6,0.2,1.8,0.9,15
Kopfsalat,14,1.2,0.2,1.1,1.4,20
Schalotte,25,1.5,0.2,3.3,1.5,37
Gemüsebrühe verz,7,1.6,0,0,0,12
Fleischbrühe,4,0.2,0,1,0,5
@ -122,7 +116,6 @@ Paprika rot,43,1.3,0.5,6.4,3.6,10
Knollensellerie,27,1.6,0.3,2.3,4.2,50
Erdbeeren tiefgefroren,38,0.9,0.4,5.8,2.1,24
Himbeeren tiefgefroren,45,1.4,0.3,5.0,4.8,42
Dill,65,3.7,0.8,8.0,5.3,230
Kerbel,58,4.1,0.6,6.2,5.3,400
Majoran,52,2.1,1.1,6.9,2.9,322
Oregano,72,2.2,2.0,9.7,2.5,310

1 name kcal EW Fett KH BST Ca
6 Pflanzenmargarine 722 0.2 80.0 0.4 0.0 8
7 Sahne 30% 309 2.4 31.7 3.4 0.0 80
8 Maisstärke 353 0.4 0.1 85.9 1.0 0
Paniermehl 368 10.1 2.1 73.5 5.3 50
9 Weizengrieß 335 9.6 0.8 69.0 7.1 17
10 Mehl405 343 9.8 1.0 71.8 4.0 15
11 Rapsöl 884 0 100.0 0 0 0
42 Senf 88 6.0 4.0 6.0 1.0 124
43 Blattspinat roh 21 2.7 0.3 0.6 2.6 117
44 Buttermilch 37 3.5 0.5 4.0 0.0 109
Himbeere 37 1.3 0.3 4.8 4.7 40
45 Salz dill gurken 9 0.4 0.1 1.3 0.5 18
46 Schmand 20% 205 2.8 20.0 3.6 0.0 100
47 Aspikpulver 338 84.2 0.1 0.0 0.0 11
48 Lachs atlantischer 210 20.4 13.4 0.3 0.0 4
49 Pinienkerne 589 24.0 50.7 7.3 7.2 26
Zwieback 385 9.9 4.3 73.1 5.2 42
50 Speisequark 72 13.5 0.3 3.2 0.0 92
51 Basilikum 47 3.1 0.8 5.1 3.1 369
52 Mayonaise 50% 490 0.5 52.0 5.0 0.0 10
80 Mehl Type 405 343 9.8 1.0 71.8 4.0 15
81 Mehl Type 550 346 9.8 1.1 72.0 4.3 17
82 Milchreis 316 6.4 0.8 80.2 1.1 6
Kartoffelstärke 341 0.6 0.1 83.1 0.1 35
83 Hmilch fettarm 1.5% 47 3.4 1.5 4.9 0.0 123
84 Edamer 30% 254 26.4 16.2 0 0.0 800
85 Gouda alt 48% 414 24.6 33.7 0.1 0.0 871
94 Zwieback 385 9.9 4.3 73.1 5.2 42
95 Schokolade 75% Kakaomasse 598 7.8 42.6 35.0 10.9 73
96 Paniermehl 368 10.1 0.1 73.5 5.3 50
Senf 88 6.0 4.0 6.0 1.0 124
97 Schinken geräuchert 152 20.7 7.7 0.0 0.0 2
98 Rinderkeule 148 20.0 7.6 0.0 0.0 6
99 Kirsche süß 62 0.9 0.3 13.3 1.3 17
102 Endivie 18 1.8 0.2 1.2 1.9 54
103 Feldsalat 18 1.8 0.4 0.8 1.5 32
104 Gurke 14 0.6 0.2 1.8 0.9 15
Kopfsalat 14 1.2 0.2 1.1 1.4 20
105 Schalotte 25 1.5 0.2 3.3 1.5 37
106 Gemüsebrühe verz 7 1.6 0 0 0 12
107 Fleischbrühe 4 0.2 0 1 0 5
116 Knollensellerie 27 1.6 0.3 2.3 4.2 50
117 Erdbeeren tiefgefroren 38 0.9 0.4 5.8 2.1 24
118 Himbeeren tiefgefroren 45 1.4 0.3 5.0 4.8 42
Dill 65 3.7 0.8 8.0 5.3 230
119 Kerbel 58 4.1 0.6 6.2 5.3 400
120 Majoran 52 2.1 1.1 6.9 2.9 322
121 Oregano 72 2.2 2.0 9.7 2.5 310

View File

@ -46,13 +46,30 @@ button#remove-button:not(:disabled):hover {
background-color: #490000; /* Dunkleres Rot */
}
table {
width: 100%;
border-collapse: collapse;
border-collapse: separate; /* Erlaubt die Anwendung von border-radius */
border-spacing: 0;
border-radius: 10px;
}
table th:first-child {
border-top-left-radius: 10px;
}
table th:last-child {
border-top-right-radius: 10px;
}
table tr:last-child td:first-child {
border-bottom-left-radius: 10px;
}
table tr:last-child td:last-child {
border-bottom-right-radius: 10px;
}
table, th, td {
border: 1px solid #ddd;
}
@ -72,7 +89,7 @@ tr:nth-child(even) {
}
.selected, tr.selected {
background-color: #e5b5b5; /* Hervorhebung der Auswahl */
background-color: #efcccc; /* Hervorhebung der Auswahl */
}
tr:hover:not(.selected) {
@ -89,9 +106,20 @@ tr:hover:not(.selected) {
border-radius: 10px;
}
#navbar .navbar-header {
display: flex;
align-items: center;
}
#navbar h1 {
margin: 0;
font-size: 24px;
display: inline-block;
}
#navbar .versionid {
margin-left: 20px;
display: inline-block;
}
#navbar ul {
@ -113,13 +141,10 @@ tr:hover:not(.selected) {
transition: background-color 0.3s;
}
#navbar a:hover {
#navbar a:hover, #navbar a.active {
background-color: #007344; /* Etwas helleres Grün */
}
#navbar a.active {
background-color: #008C50; /* Mittleres Grün */
}
.content {
@ -130,10 +155,8 @@ tr:hover:not(.selected) {
}
#nutrition-input-table {
width: 100%; /* Tabelle nimmt die volle Breite ein */
border-collapse: collapse; /* Entfernt doppelte Ränder */
}
#nutrition-input-table th, #nutrition-input-table td {
border: 1px solid #ddd; /* Fügt Ränder hinzu */
@ -153,16 +176,17 @@ tr:hover:not(.selected) {
}
}
#table-container {
.table-container {
overflow-y: auto;
max-height: 400px; /* Passen Sie die Höhe nach Bedarf an */
max-height: 500px; /* Passen Sie die Höhe nach Bedarf an */
border-radius: 10px;
margin-top: 20px;
}
#database-nutrition-table {
width: 100%;
border-collapse: collapse;
border-collapse: separate; /* Erlaubt die Anwendung von border-radius */
border-spacing: 0;
}
#database-nutrition-table th, #database-nutrition-table td {
@ -172,7 +196,7 @@ tr:hover:not(.selected) {
}
#database-nutrition-table tr.selected {
background-color: #f0e68c;
background-color: #efcccc;
}
@ -183,34 +207,28 @@ tr:hover:not(.selected) {
justify-content: center;
}
#password-prompt input[type="password"] {
padding: 8px;
margin-right: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
#password-prompt button {
padding: 8px 15px;
margin-right: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
color: white;
}
#password-prompt button[type="submit"] {
background-color: #008C50; /* Helles Grün */
}
#password-prompt button[type="submit"]:hover {
background-color: #007344; /* Dunkleres Grün */
}
#password-prompt button[type="button"] {
button#delete-row-button {
background-color: #640000; /* Helles Rot */
}
#password-prompt button[type="button"]:hover {
button#delete-row-button:disabled {
background-color: #cccccc;
color: #666666;
}
button#delete-row-button:not(:disabled):hover {
background-color: #490000; /* Dunkleres Rot */
}
button#cancel-button {
background-color: #640000; /* Helles Rot */
}
button#cancel-button:disabled {
background-color: #cccccc;
color: #666666;
}
button#cancel-button:not(:disabled):hover {
background-color: #490000; /* Dunkleres Rot */
}

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nährwertberechnungs-App</title>
<title>Elo's Rezept Rechner</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
<link rel="shortcut icon" href="../static/images/favicon.ico">
@ -175,7 +175,10 @@ function updateTotalNutrition() {
</head>
<body>
<nav id="navbar">
<div class="navbar-header">
<h1>Elo's Rezept Rechner</h1>
<li class="versionid">VERSION_ID</li>
</div>
<ul>
<li><a href="/" class="active">Rechner</a></li>
<li><a href="/nutrition">Neue Lebensmittel</a></li>

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Neue Lebensmittel hinzufügen</title>
<title>Elo's Rezept Rechner</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
<link rel="shortcut icon" href="../static/images/favicon.ico">
@ -40,6 +40,7 @@
// Beispielsweise das Formular zurücksetzen
form.reset();
updateSubmitButtonState();
loadDatabaseEntries();
}).catch(error => {
console.error('Fehler:', error);
});
@ -69,13 +70,33 @@
function deleteSelectedRows() {
const table = document.getElementById('database-nutrition-table');
Array.from(table.rows).forEach(row => {
if (row.classList.contains('selected')) {
// Logik zum Löschen der Zeile aus der Datenbank
const selectedRows = Array.from(table.querySelectorAll('tr.selected'));
const foodNames = selectedRows.map(row => row.cells[0].innerText); // Annahme, der Name des Lebensmittels befindet sich in der ersten Zelle
if (foodNames.length > 0) {
// Holen des Tokens und Senden einer Anfrage an das Backend, um die Einträge zu löschen
getBearerToken(token => {
fetch('/delete_nutrition', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({foodNames: foodNames})
}).then(response => {
if (response.ok) {
// Erfolgreich gelöscht, entferne Zeilen aus der Tabelle
selectedRows.forEach(row => {
table.deleteRow(row.rowIndex);
});
} else {
console.error('Fehler beim Löschen der Datenbank-Einträge');
}
}).catch(error => console.error('Fehler:', error));
});
}
}
function showPasswordPrompt() {
document.getElementById('delete-row-button').style.display = 'none';
@ -89,7 +110,7 @@
function deleteRowsIfPasswordCorrect() {
const password = document.getElementById('password-input').value;
if (password === 'wowmuchsecurity') {
if (password === 'geheim') {
deleteSelectedRows(); // Funktion, die die ausgewählten Zeilen löscht
hidePasswordPrompt();
} else {
@ -98,7 +119,7 @@
}
function updateDeleteButtonState() {
const selectedRows = document.querySelectorAll('#nutrition-table .selected').length;
const selectedRows = document.querySelectorAll('#database-nutrition-table .selected').length;
const deleteButton = document.getElementById('delete-row-button');
deleteButton.disabled = selectedRows === 0;
if (selectedRows === 0) {
@ -107,11 +128,13 @@
}
function loadDatabaseEntries() {
fetch('/get_database_entries') // Pfad zur entsprechenden Flask-Route
.then(response => response.json())
.then(data => {
const tableBody = document.getElementById('database-nutrition-table').getElementsByTagName('tbody')[0];
tableBody.innerHTML = '';
data.forEach(entry => {
const row = tableBody.insertRow();
row.insertCell(0).innerHTML = entry.food;
@ -130,18 +153,41 @@
document.addEventListener('DOMContentLoaded', loadDatabaseEntries);
function filterTable() {
const searchInput = document.getElementById('search-input');
const filterText = searchInput.value.toUpperCase();
const table = document.getElementById('database-nutrition-table');
const rows = table.getElementsByTagName('tr');
for (let i = 1; i < rows.length; i++) { // Beginnen bei 1, um die Kopfzeile auszulassen
const cell = rows[i].getElementsByTagName('td')[0]; // Angenommen, der zu suchende Text befindet sich in der ersten Spalte
if (cell) {
const textValue = cell.textContent || cell.innerText;
if (textValue.toUpperCase().indexOf(filterText) > -1) {
rows[i].style.display = ""; // Zeile anzeigen
} else {
rows[i].style.display = "none"; // Zeile verstecken
}
}
}
}
</script>
</head>
<body>
<nav id="navbar">
<div class="navbar-header">
<h1>Elo's Rezept Rechner</h1>
<li class="versionid">VERSION_ID</li>
</div>
<ul>
<li><a href="/">Rechner</a></li>
<li><a href="/nutrition" class="active">Neue Lebensmittel</a></li>
</ul>
</nav>
<div class="content">
<form onsubmit="event.preventDefault(); addNutritionEntry();" method="POST" id="nutrition-form">
<table id="nutrition-input-table">
@ -167,7 +213,12 @@ document.addEventListener('DOMContentLoaded', loadDatabaseEntries);
<button type="submit" id="submit-button" disabled>Hinzufügen</button>
</form>
<div id="table-container">
<div class="search-container">
<input type="text" id="search-input" placeholder="Lebensmittel suchen..." oninput="filterTable()">
</div>
<div class="table-container">
<table id="database-nutrition-table">
<thead>
<tr>
@ -189,8 +240,8 @@ document.addEventListener('DOMContentLoaded', loadDatabaseEntries);
<div id="password-prompt" style="display: none;">
<input type="password" id="password-input" placeholder="Passwort">
<button onclick="deleteRowsIfPasswordCorrect()">OK</button>
<button onclick="hidePasswordPrompt()">Abbrechen</button>
<button id="ok-button" onclick="deleteRowsIfPasswordCorrect()">OK</button>
<button id="cancel-button" onclick="hidePasswordPrompt()">Abbrechen</button>
</div>

View File

@ -1,6 +1,6 @@
#!/bin/sh
gunicorn 'Run:app' --bind 0.0.0.0:8080 --log-level=info --workers=4
gunicorn 'Run:exposed_app' --bind 0.0.0.0:8080 --log-level=debug --workers=4