From d3b29052e8f799357c588bbd57d82adb1488571d Mon Sep 17 00:00:00 2001 From: ske087 Date: Thu, 17 Apr 2025 10:00:46 +0300 Subject: [PATCH] created user settings in the settings page --- py_app/app/__init__.py | 12 +- .../app/__pycache__/__init__.cpython-311.pyc | Bin 652 -> 1242 bytes py_app/app/__pycache__/models.cpython-311.pyc | Bin 0 -> 1110 bytes py_app/app/__pycache__/routes.cpython-311.pyc | Bin 2300 -> 8210 bytes py_app/app/models.py | 10 ++ py_app/app/routes.py | 116 ++++++++++++- py_app/app/static/script.js | 89 ++++++++++ py_app/app/static/style.css | 155 ++++++++++++++++-- py_app/app/templates/login.html | 6 +- py_app/app/templates/quality.html | 6 + py_app/app/templates/scan.html | 6 + py_app/app/templates/settings.html | 75 ++++++++- py_app/app/templates/warehouse.html | 6 + py_app/instance/users.db | Bin 0 -> 12288 bytes py_app/requirements.txt | 3 +- py_app/seed.py | 22 +++ 16 files changed, 478 insertions(+), 28 deletions(-) create mode 100644 py_app/app/__pycache__/models.cpython-311.pyc create mode 100644 py_app/app/models.py create mode 100644 py_app/app/templates/quality.html create mode 100644 py_app/app/templates/scan.html create mode 100644 py_app/app/templates/warehouse.html create mode 100644 py_app/instance/users.db create mode 100644 py_app/seed.py diff --git a/py_app/app/__init__.py b/py_app/app/__init__.py index b828291..f9429e8 100644 --- a/py_app/app/__init__.py +++ b/py_app/app/__init__.py @@ -1,10 +1,20 @@ from flask import Flask +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() def create_app(): app = Flask(__name__) - app.config['SECRET_KEY'] = 'Recticel a plecat Aquinos a falimentat Innofa a venit' + app.config['SECRET_KEY'] = 'your_secret_key' + app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + + db.init_app(app) from .routes import bp app.register_blueprint(bp) + with app.app_context(): + db.create_all() # Create database tables if they don't exist + return app \ No newline at end of file diff --git a/py_app/app/__pycache__/__init__.cpython-311.pyc b/py_app/app/__pycache__/__init__.cpython-311.pyc index deb45865c85a501b311990b4ef968dcd88c39381..cb93869e091ea4eec2bfeb6c892b07174e5a3d09 100644 GIT binary patch literal 1242 zcmZWo%}X0W6rbIl#3X9Bh^-|pDi+!Xifda6Qfz6Ak;eEzO?pU>4lz4w>gL1U4Vn@m zEkacUdnxwl$x{3)>R*r)pqpM&Fm09!~#GN+(47w0&Jd4*34ae+fTqQVYX>{@;(j%8s5#T_z^AfMxi z$$gyR7*-P6JOEGR`KVt>&e3!sS@!|pgeky0ehHauAsx6yx|ItEc0j&c*DXU%gH*^G$RQX?T%e5@Ki(vW-D>mI-vlJ#L7F zY+fZAO{!EU^Rxhc2?i#EQ4$WuUbkrrN=m1XBuUC^RMmRrX`_SnZ8Y#KI2I#A{-}S@ z9|@8dlc8awvq2M`^asLZY+@)h918fOp^5Rx5$hH-o}bS7JSuCk;UXlHNK--#XEK|a zNzEEOoZw1jQaVZGa)wjQ=5?y6&CIw>rL!qbrz)9N@-(NWGP=vix}+N(xI;px zB%vri-Vi`#I%=#M-QB1C(p)x8rCdrHqT0Nk%}ERS1YEB`RGQRNNvcS>0y|b>lMpit z(wl>lSb-tpRS3qOi}nLp2_1OE53V(7Ln;NTU45m%%E)T5f^SssK4rKp-l{5JevsNnW}++N1*huB-Tk1B5ZhP_|0_v8Hv?%cZ>@zwBj?^o_PF(}( ztejWq6ZJZ5*}KrjfI3MZW&1dEh^6?Osgu1#OcR AZvX%Q delta 431 zcmZWlze~eF6u!%kwpN-#mv#{Bq-N5^O$2Q#SfOAmf?YzITuSir!%I>`s&?q0(4|z- z(M|ksbSn{8pyGP?!EWj_dYIO7|6AhiF=yFg(|?+i`+>0-x?LZv_e$gC<6fy>z3IM5OQS1swX>-7sxx4rnkvS! z#Xn+hf^m%(#IkU(48T`v%kj*Jl5LiQl)DZ#0Hz|wc#QI|f7et>;_MXthq>Ypji_)J diff --git a/py_app/app/__pycache__/models.cpython-311.pyc b/py_app/app/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ed0bdeb56045fc433a435788df8a32603380e18 GIT binary patch literal 1110 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 delta 1178 zcmZWn%}*0S6rb7ccDF74;Hxba3L+wP1wjdFL{K8}R-;CZaKOT>l-Om-?1Bb~5<_B* z7jYnR(1a6`z|}v(c%j$>S%dN7!HcQ!VvLEtDQSW7lKJI*{NBv_z1>$A|CamSdA)7~ zc5e0G=m&A$7Z&>Pd`nA{fHX`5O<55TT7$D=11=&G#~2=PYp!JvyM!w{5Rr(J$fLq~ z375F$&2kk|%ADfVH7jXA<(@%xTjF(-x}ZWO z4qPGSBU1-JOrQbo^Vdx-iD747JOmD>n2!Kv(Kp#Q_joC|Dc5hv_1l5aLfO*oY~W~G z+OCW&bT7NJm1>{)x7u?5o78G@GupKg?b?bSVeg%va0PoVpN)j!J{knD zT_j;9hm8a!v=-tj_E|oU!%XovV!~8^J6o>~vnz7FJ0`|y1#gS6kN(K9L)_iH#+fok zjY*5vLplP-JPrU8vuL2@38ziFPMVr!jg60*BM=r%1dpFz4FIo^Rs3NQBKW}ih4{3$ za7|m%(o->g^4_orQVE3&3e=ghniOqj|Et7oqAmv8X8aN z+R%_K3{TK%pxY7!Q5xmnA-|ryK7J=EdGU|Zts7)ArS;HesB#sig4y@F3w2*5-|U_A z)XRq%sUa&h%nCUtaz~cBHk8I$i48_;LM|N3A%LGE5?ZtPL{8wDAbSyQzZuKmsw}R` p2?ADg2!NBSix~w8j%VSg;k25;!7L8u1PuKMfb&B8GWm2~@qZ6K^aua| diff --git a/py_app/app/models.py b/py_app/app/models.py new file mode 100644 index 0000000..73b4e22 --- /dev/null +++ b/py_app/app/models.py @@ -0,0 +1,10 @@ +from . import db + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(80), unique=True, nullable=False) + password = db.Column(db.String(120), nullable=False) + role = db.Column(db.String(20), nullable=False) # Role: superadmin, administrator, quality, warehouse, scan + + def __repr__(self): + return f'' \ No newline at end of file diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 0612728..8980201 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -1,17 +1,18 @@ from flask import Blueprint, render_template, redirect, url_for, request, flash, session +from .models import User +from . import db bp = Blueprint('main', __name__) -# Dummy user data -users = {"admin@home.com": "1234"} - @bp.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': - email = request.form['email'] + username = request.form['username'] password = request.form['password'] - if email in users and users[email] == password: - session['user'] = email + user = User.query.filter_by(username=username, password=password).first() + if user: + session['user'] = user.username + session['role'] = user.role return redirect(url_for('main.dashboard')) else: flash('Invalid credentials. Please try again.') @@ -23,11 +24,108 @@ def dashboard(): return redirect(url_for('main.login')) return render_template('dashboard.html') +@bp.route('/settings') +def settings(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.dashboard')) + + # Fetch all users from the database + users = User.query.all() + return render_template('settings.html', users=users) + +@bp.route('/quality') +def quality(): + if 'role' not in session or session['role'] not in ['superadmin', 'quality']: + flash('Access denied: Quality users only.') + return redirect(url_for('main.dashboard')) + return render_template('quality.html') + +@bp.route('/warehouse') +def warehouse(): + if 'role' not in session or session['role'] not in ['superadmin', 'warehouse']: + flash('Access denied: Warehouse users only.') + return redirect(url_for('main.dashboard')) + return render_template('warehouse.html') + +@bp.route('/scan') +def scan(): + if 'role' not in session or session['role'] not in ['superadmin', 'scan']: + flash('Access denied: Scan users only.') + return redirect(url_for('main.dashboard')) + return render_template('scan.html') + @bp.route('/logout') def logout(): session.pop('user', None) + session.pop('role', None) return redirect(url_for('main.login')) -@bp.route('/settings') -def settings(): - return render_template('settings.html') \ No newline at end of file +@bp.route('/create_user', methods=['POST']) +def create_user(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + username = request.form['username'] + password = request.form['password'] + role = request.form['role'] + + # Check if the username already exists + if User.query.filter_by(username=username).first(): + flash('User already exists.') + return redirect(url_for('main.settings')) + + # Create a new user + new_user = User(username=username, password=password, role=role) + db.session.add(new_user) + db.session.commit() + + flash('User created successfully.') + return redirect(url_for('main.settings')) + +@bp.route('/edit_user', methods=['POST']) +def edit_user(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + user_id = request.form['user_id'] + password = request.form['password'] + role = request.form['role'] + + # Fetch the user from the database + user = User.query.get(user_id) + if not user: + flash('User not found.') + return redirect(url_for('main.settings')) + + # Update the user's details + if password: + user.password = password + user.role = role + db.session.commit() + + flash('User updated successfully.') + return redirect(url_for('main.settings')) + +@bp.route('/delete_user', methods=['POST']) +def delete_user(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + user_id = request.form['user_id'] + + # Fetch the user from the database + user = User.query.get(user_id) + if not user: + flash('User not found.') + return redirect(url_for('main.settings')) + + # Delete the user + db.session.delete(user) + db.session.commit() + + flash('User deleted successfully.') + return redirect(url_for('main.settings')) \ No newline at end of file diff --git a/py_app/app/static/script.js b/py_app/app/static/script.js index 0ec2000..d3ad383 100644 --- a/py_app/app/static/script.js +++ b/py_app/app/static/script.js @@ -31,4 +31,93 @@ document.addEventListener('DOMContentLoaded', () => { themeToggle.textContent = 'Change to light theme'; } } + + const createUserBtn = document.getElementById('create-user-btn'); + const createUserPopup = document.getElementById('create-user-popup'); + const closePopupBtn = document.getElementById('close-popup-btn'); + + // Open the popup + createUserBtn.addEventListener('click', () => { + createUserPopup.style.display = 'flex'; + }); + + // Close the popup + closePopupBtn.addEventListener('click', () => { + createUserPopup.style.display = 'none'; + }); + + // Close the popup when clicking outside the popup content + createUserPopup.addEventListener('click', (e) => { + if (e.target === createUserPopup) { + createUserPopup.style.display = 'none'; + } + }); + + const editButtons = document.querySelectorAll('.edit-btn'); + const editUserPopup = document.getElementById('edit-user-popup'); + const closeEditPopupBtn = document.getElementById('close-edit-popup-btn'); + + // Open the edit user popup + editButtons.forEach((button) => { + button.addEventListener('click', (e) => { + const userElement = e.target.closest('li'); + const username = userElement.querySelector('.user-name').textContent; + const role = userElement.querySelector('.user-role').textContent.split(': ')[1]; + const userId = userElement.dataset.userId; + + // Populate the form fields + document.getElementById('edit-user-id').value = userId; + document.getElementById('edit-username').value = username; + document.getElementById('edit-role').value = role; + + // Show the popup + editUserPopup.style.display = 'flex'; + }); + }); + + // Close the edit user popup + closeEditPopupBtn.addEventListener('click', () => { + editUserPopup.style.display = 'none'; + }); + + // Close the popup when clicking outside the popup content + editUserPopup.addEventListener('click', (e) => { + if (e.target === editUserPopup) { + editUserPopup.style.display = 'none'; + } + }); + + const deleteButtons = document.querySelectorAll('.delete-btn'); + const deleteUserPopup = document.getElementById('delete-user-popup'); + const closeDeletePopupBtn = document.getElementById('close-delete-popup-btn'); + const deleteUsernameSpan = document.getElementById('delete-username'); + const deleteUserIdInput = document.getElementById('delete-user-id'); + + // Open the delete user popup + deleteButtons.forEach((button) => { + button.addEventListener('click', (e) => { + const userElement = e.target.closest('li'); + const username = userElement.querySelector('.user-name').textContent; + const userId = userElement.dataset.userId; + + // Populate the popup with user details + deleteUsernameSpan.textContent = username; + deleteUserIdInput.value = userId; + + // Show the popup + deleteUserPopup.style.display = 'flex'; + }); + }); + + // Close the delete user popup + closeDeletePopupBtn.addEventListener('click', () => { + deleteUserPopup.style.display = 'none'; + }); + + // Close the popup when clicking outside the popup content + deleteUserPopup.addEventListener('click', (e) => { + if (e.target === deleteUserPopup) { + deleteUserPopup.style.display = 'none'; + } + }); }); \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index cbfe929..a734b6d 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -6,7 +6,7 @@ body { } .container { - width: 98%; + width: 100%; margin: auto; overflow: hidden; padding: 0; /* Remove padding */ @@ -17,10 +17,11 @@ body { .login-page { display: flex; - align-items: center; - justify-content: center; - height: 100vh; + align-items: center; /* Vertically center the content */ + justify-content: space-between; /* Space between the logo and the form container */ + height: 100vh; /* Full height of the viewport */ background-color: #f4f4f9; + padding: 0 20px; /* Add padding to the sides */ } header { @@ -92,12 +93,13 @@ header { } .form-container { - width: 600px; /* Set a fixed width for the login container */ + width: 600px; /* Fixed width for the login container */ background: #fff; - padding: 15px 30px 15px 15px; /* Add 30px padding to the right */ + padding: 15px 30px; /* Add padding inside the container */ border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - margin: 0 0 0 20px; /* Move the container closer to the picture */ + margin: 0; /* Remove any extra margin */ + align-self: center; /* Vertically center the form container */ } .form-container h2 { @@ -228,18 +230,17 @@ body.dark-mode .card { /* Common card styles */ .card { - width: 400px; /* Fixed width */ - height: 150px; /* Fixed height */ + width: 600px; + background: #fff; border-radius: 5px; padding: 20px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - margin: 20px auto; /* Center the card horizontally */ + margin: 20px auto; text-align: center; - transition: background-color 0.3s ease, color 0.3s ease, border 0.3s ease; } .card h3 { - margin-bottom: 10px; + margin-bottom: 20px; font-size: 1.5em; } @@ -261,4 +262,134 @@ body.dark-mode .card { .card .btn:hover { background-color: #0056b3; +} + +.user-list { + list-style: none; + padding: 0; + margin: 0 0 20px 0; +} + +.user-list li { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 0; + border-bottom: 1px solid #ddd; +} + +.user-name { + font-size: 1em; + font-weight: bold; +} + +.user-role { + font-size: 0.9em; + color: #555; + margin-left: 10px; +} + +.btn { + padding: 5px 10px; + font-size: 1em; + color: #fff; + background-color: #007bff; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.btn:hover { + background-color: #0056b3; +} + +.create-btn { + margin-top: 20px; + background-color: #28a745; +} + +.create-btn:hover { + background-color: #218838; +} + +.popup { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + justify-content: center; + align-items: center; +} + +/* Light mode styles for pop-ups */ +body.light-mode .popup-content { + background: #fff; + color: #000; + border: 1px solid #ddd; +} + +/* Dark mode styles for pop-ups */ +body.dark-mode .popup-content { + background: #1e1e1e; + color: #fff; + border: 1px solid #444; +} + +/* Common styles for pop-ups */ +.popup-content { + padding: 20px; + border-radius: 5px; + width: 400px; + text-align: center; + transition: background-color 0.3s ease, color 0.3s ease, border 0.3s ease; +} + +.popup-content h3 { + margin-bottom: 20px; + font-size: 1.2em; +} + +.popup-content form { + display: flex; + flex-direction: column; +} + +.popup-content label { + margin-bottom: 5px; + font-weight: bold; +} + +.popup-content input, +.popup-content select { + margin-bottom: 15px; + padding: 10px; + font-size: 1em; + border: 1px solid #ccc; + border-radius: 5px; + width: 100%; +} + +.popup-content input[readonly] { + background-color: #e9ecef; + cursor: not-allowed; +} + +.cancel-btn { + background-color: #dc3545; +} + +.cancel-btn:hover { + background-color: #c82333; +} + +.delete-confirm-btn { + background-color: #dc3545; +} + +.delete-confirm-btn:hover { + background-color: #c82333; } \ No newline at end of file diff --git a/py_app/app/templates/login.html b/py_app/app/templates/login.html index a1f1100..d09fab4 100644 --- a/py_app/app/templates/login.html +++ b/py_app/app/templates/login.html @@ -10,10 +10,10 @@

Login

- - + + - +
diff --git a/py_app/app/templates/quality.html b/py_app/app/templates/quality.html new file mode 100644 index 0000000..a06480a --- /dev/null +++ b/py_app/app/templates/quality.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% block title %}Quality Module{% endblock %} +{% block content %} +

Quality Module

+

Welcome to the Quality Module.

+{% endblock %} \ No newline at end of file diff --git a/py_app/app/templates/scan.html b/py_app/app/templates/scan.html new file mode 100644 index 0000000..06a0a89 --- /dev/null +++ b/py_app/app/templates/scan.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% block title %}Scan Module{% endblock %} +{% block content %} +

Scan Module

+

Welcome to the Scan Module.

+{% endblock %} \ No newline at end of file diff --git a/py_app/app/templates/settings.html b/py_app/app/templates/settings.html index c95efc6..d0036fd 100644 --- a/py_app/app/templates/settings.html +++ b/py_app/app/templates/settings.html @@ -3,6 +3,77 @@ {% block title %}Settings{% endblock %} {% block content %} -

Settings Page

-

This is the settings page. Add your settings here.

+
+

Manage Users

+
    + {% for user in users %} +
  • + {{ user.username }} + Role: {{ user.role }} + + +
  • + {% endfor %} +
+ +
+ + + + + + + + + {% endblock %} \ No newline at end of file diff --git a/py_app/app/templates/warehouse.html b/py_app/app/templates/warehouse.html new file mode 100644 index 0000000..99dd436 --- /dev/null +++ b/py_app/app/templates/warehouse.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% block title %}Warehouse Module{% endblock %} +{% block content %} +

Warehouse Module

+

Welcome to the Warehouse Module.

+{% endblock %} \ No newline at end of file diff --git a/py_app/instance/users.db b/py_app/instance/users.db new file mode 100644 index 0000000000000000000000000000000000000000..4b807a39048006ac9446f8cceb1cb987d047d21d GIT binary patch literal 12288 zcmeI$O>5LZ7zgl~%}d>dWr`5CQe-E>x(SH5Z4ZJMV+nR~jW+HIJuPDsF|eDod7*mL zui)3{S-*gHkNOcjd-CW^=w`K-p2W*PFqvmE&oIL;r+Ho+PLeX_ud{q9O1?`r38myA z=Y$YbHchtGLuH_^2C`SpDsetiZ*{M~raZf{nQV`+ z@9Z=C$PyOF0UiiI00Izz00bZa0SG_<0uX=z1jv?Yke+3av$QHlJG*;DbrREec4ul%ut=98^j&-&qN--$>bHho^M7nsfllC1{v7fr=XORzTg)_ z00Izz00bZa0SG_<0uX=z1R(JL1ln4U)