From fc355333cbd7a0829982a2f911f23b6d8303e906 Mon Sep 17 00:00:00 2001 From: ske087 Date: Thu, 17 Apr 2025 13:42:46 +0300 Subject: [PATCH] added external server settings save to the settings page --- external_database_settings | 5 + .../app/__pycache__/__init__.cpython-311.pyc | Bin 1242 -> 1242 bytes py_app/app/__pycache__/routes.cpython-311.pyc | Bin 8210 -> 10979 bytes py_app/app/routes.py | 41 ++++++++- py_app/app/static/style.css | 87 +++++++++++++++++- py_app/app/templates/settings.html | 45 ++++++--- py_app/instance/external_server.conf | 5 + 7 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 external_database_settings create mode 100644 py_app/instance/external_server.conf diff --git a/external_database_settings b/external_database_settings new file mode 100644 index 0000000..ce3855e --- /dev/null +++ b/external_database_settings @@ -0,0 +1,5 @@ +Server Domain/IP Address: testserver.com +Port: 3602 +Database Name: recticel +Username: sa +Password: 12345678 diff --git a/py_app/app/__pycache__/__init__.cpython-311.pyc b/py_app/app/__pycache__/__init__.cpython-311.pyc index cb93869e091ea4eec2bfeb6c892b07174e5a3d09..7db3f91f741048fc0e22a178ac97840143cc9a86 100644 GIT binary patch delta 19 Zcmcb`d5e>4IWI340}#aQ-^g`=1pqa{1x5e> delta 19 Zcmcb`d5e>4IWI340}$9w-^g`=1pqWZ1pfd4 diff --git a/py_app/app/__pycache__/routes.cpython-311.pyc b/py_app/app/__pycache__/routes.cpython-311.pyc index 0a927613a45e5da0d0fe42b73036e42076394bc1..bd42740146ca871ffd7cedb6a934a08f9fea0cac 100644 GIT binary patch literal 10979 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 Apa1{> delta 1900 zcmb7E&u<$=6yDjjckQfyWo@q=+i^pwDN7ocDk^nJ2&oXF2o#W@Dy)z!H@k8y?b>11 zp;ASJkhpNFU=DC8sssd~MinRm@edR(2vX5Xuo49caez}eA@u_9%{po94F^U$Pc!d* z@69*wz1iQ+y}OwDB$*r&V0`_tu(FW0ad>wJdT-8*GAPP3IqIO~fB3*+S3^Qpb8M(hOBU_3UYm1xl zVY@ZIMNl%wSlF5Hd4BCP$E|5OREgOphQlA*41yj*lR<5HdSJ zW=D{@5HdGF=0}iv2$>I%(*?*C3FWF7!s`S4#DVxy2ww>BkCYF@S3>xrHTi;IRR6#d z7z$gG&Tf4u{X|Hbtw&3;23neBSE3!FGDV(Lxgw6*JUcFzf_)bEIrgIbOmq^K%GO8n zA|W~UyV59C(N+QB$E}vPa-r9v7Cj96JUbPeOQZQx{J3ZL`<-svV>dH8`I9}D*4g#g z7f1VPFb{?meO=g;hkFZ{D@(xS&e(~n4!BFn-9Yt~zUzES{OFozQ_qO8mYQ#<0HG5g ze5vI)G=kd)KzP`KQvu7^ZUkz8vW(U?do`o8JGBa{YZ_ZlWQ#wmrS~8IthTK-ZmNx2 zYGXUnpm-DZX7amO9u|g3kFfKp6GUfkr)DPZ0~H7GGw3vKQPkM?sh3HW8R;MHxkWN3 zXZdAP7hBX`>A?;7ZRjy{8wpiM9g1Vj$(Ru8o6J52SH`F7JXG9UZgu}V%EK51#Vin- zWLa$N2%keVd!;X)rCq^zwv#UVegIE!+m~uN8Y@ zb(lLn2`FE|c+HLl4@4?I+Zv|lOKrPP`ODzG$dR4`0o>+reb0nR_J(Q2ZL8A{NG*W% zJR<%cwBZc<^-zNSQ{Dt_o0X@;(gECpBj#E1(A>FUUi2|MoM%k7Y{%}~0V^?Z;au?F zzL%f?6mU5MhE?S9%RVkw6>R+_V}ji{`p_G`?DoLLPIQG zhfVQU!T$vOr3H_Iw=?fX>>geaiV2{2@<^lIjm^VRYmU7@&w`b}^bRio_Z^84@}uz5 p_W%FbjR!v{DCG2x0OBu65DT}6z9XVW+gdjak`gph-$B9O^S`6=eTM)5 diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 8980201..a964cee 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -1,4 +1,5 @@ -from flask import Blueprint, render_template, redirect, url_for, request, flash, session +import os +from flask import Blueprint, render_template, redirect, url_for, request, flash, session, current_app from .models import User from . import db @@ -32,7 +33,17 @@ def settings(): # Fetch all users from the database users = User.query.all() - return render_template('settings.html', users=users) + + # Load external database settings from the instance folder + external_settings = {} + settings_file = os.path.join(current_app.instance_path, 'external_server.conf') + if os.path.exists(settings_file): + with open(settings_file, 'r') as f: + for line in f: + key, value = line.strip().split('=', 1) + external_settings[key] = value + + return render_template('settings.html', users=users, external_settings=external_settings) @bp.route('/quality') def quality(): @@ -128,4 +139,30 @@ def delete_user(): db.session.commit() flash('User deleted successfully.') + return redirect(url_for('main.settings')) + +@bp.route('/save_external_db', methods=['POST']) +def save_external_db(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + # Get form data + server_domain = request.form['server_domain'] + port = request.form['port'] + database_name = request.form['database_name'] + username = request.form['username'] + password = request.form['password'] + + # Save data to a file in the instance folder + settings_file = os.path.join(current_app.instance_path, 'external_server.conf') + os.makedirs(os.path.dirname(settings_file), exist_ok=True) + with open(settings_file, 'w') as f: + f.write(f"server_domain={server_domain}\n") + f.write(f"port={port}\n") + f.write(f"database_name={database_name}\n") + f.write(f"username={username}\n") + f.write(f"password={password}\n") + + flash('External database settings saved/updated successfully.') return redirect(url_for('main.settings')) \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index bcf5a4d..019630f 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -230,12 +230,12 @@ body.dark-mode .card { /* Common card styles */ .card { - width: 600px; + flex: 1 1 500px; /* Allow cards to grow and shrink, with a base width of 500px */ + max-width: 500px; /* Ensure cards don't exceed 500px in width */ background: #fff; border-radius: 5px; padding: 20px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - margin: 20px auto; text-align: center; } @@ -244,6 +244,35 @@ body.dark-mode .card { font-size: 1.5em; } +.card label { + display: block; + margin-bottom: 5px; + font-weight: bold; +} + +.card input { + width: 100%; + padding: 10px; + margin-bottom: 15px; + font-size: 1em; + border: 1px solid #ccc; + border-radius: 5px; +} + +.card button { + padding: 10px 20px; + font-size: 1em; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.card button:hover { + background-color: #0056b3; +} + .card p { margin-bottom: 20px; color: inherit; /* Inherit text color from the card */ @@ -409,4 +438,58 @@ body.dark-mode .popup-content { .go-to-dashboard-btn:hover { background-color: #0056b3; +} + +.form-centered { + display: flex; + flex-direction: column; + align-items: center; /* Center the input fields */ +} + +.form-centered label { + width: 75%; /* Align labels with the input fields */ + text-align: left; + margin-bottom: 5px; + font-weight: bold; +} + +.form-centered input { + width: 75%; /* Set input fields to 75% of the card width */ + padding: 10px; + margin-bottom: 15px; + font-size: 1em; + border: 1px solid #ccc; + border-radius: 5px; +} + +.form-centered button { + width: 50%; /* Center the button and reduce its width */ + padding: 10px; + font-size: 1em; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.form-centered button:hover { + background-color: #0056b3; +} + +/* Container for the cards */ +.card-container { + display: flex; + flex-wrap: wrap; /* Allow wrapping to the next row if needed */ + justify-content: center; /* Center the cards horizontally */ + gap: 20px; /* Add spacing between the cards */ + margin: 20px auto; /* Center the container */ + max-width: 1200px; /* Optional: Limit the maximum width of the container */ +} + +/* Media query for smaller screens */ +@media (max-width: 768px) { + .card { + flex: 1 1 100%; /* Make cards take full width on smaller screens */ + } } \ No newline at end of file diff --git a/py_app/app/templates/settings.html b/py_app/app/templates/settings.html index d0036fd..fb6e5b2 100644 --- a/py_app/app/templates/settings.html +++ b/py_app/app/templates/settings.html @@ -3,19 +3,38 @@ {% block title %}Settings{% endblock %} {% block content %} -
-

Manage Users

-
    - {% for user in users %} -
  • - {{ user.username }} - Role: {{ user.role }} - - -
  • - {% endfor %} -
- +
+
+

Manage Users

+
    + {% for user in users %} +
  • + {{ user.username }} + Role: {{ user.role }} + + +
  • + {% endfor %} +
+ +
+ +
+

External Server Settings

+
+ + + + + + + + + + + +
+
diff --git a/py_app/instance/external_server.conf b/py_app/instance/external_server.conf new file mode 100644 index 0000000..ea3c87d --- /dev/null +++ b/py_app/instance/external_server.conf @@ -0,0 +1,5 @@ +server_domain=testserver.com +port=3602 +database_name=recticel +username=test1 +password=12345678