created user settings in the settings page

This commit is contained in:
2025-04-17 10:00:46 +03:00
parent db465d6e4e
commit d3b29052e8
16 changed files with 478 additions and 28 deletions

View File

@@ -1,10 +1,20 @@
from flask import Flask from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(): def create_app():
app = Flask(__name__) 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 from .routes import bp
app.register_blueprint(bp) app.register_blueprint(bp)
with app.app_context():
db.create_all() # Create database tables if they don't exist
return app return app

Binary file not shown.

10
py_app/app/models.py Normal file
View File

@@ -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'<User {self.username}>'

View File

@@ -1,17 +1,18 @@
from flask import Blueprint, render_template, redirect, url_for, request, flash, session from flask import Blueprint, render_template, redirect, url_for, request, flash, session
from .models import User
from . import db
bp = Blueprint('main', __name__) bp = Blueprint('main', __name__)
# Dummy user data
users = {"admin@home.com": "1234"}
@bp.route('/login', methods=['GET', 'POST']) @bp.route('/login', methods=['GET', 'POST'])
def login(): def login():
if request.method == 'POST': if request.method == 'POST':
email = request.form['email'] username = request.form['username']
password = request.form['password'] password = request.form['password']
if email in users and users[email] == password: user = User.query.filter_by(username=username, password=password).first()
session['user'] = email if user:
session['user'] = user.username
session['role'] = user.role
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
else: else:
flash('Invalid credentials. Please try again.') flash('Invalid credentials. Please try again.')
@@ -23,11 +24,108 @@ def dashboard():
return redirect(url_for('main.login')) return redirect(url_for('main.login'))
return render_template('dashboard.html') 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') @bp.route('/logout')
def logout(): def logout():
session.pop('user', None) session.pop('user', None)
session.pop('role', None)
return redirect(url_for('main.login')) return redirect(url_for('main.login'))
@bp.route('/settings') @bp.route('/create_user', methods=['POST'])
def settings(): def create_user():
return render_template('settings.html') 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'))

View File

@@ -31,4 +31,93 @@ document.addEventListener('DOMContentLoaded', () => {
themeToggle.textContent = 'Change to light theme'; 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';
}
});
}); });

View File

@@ -6,7 +6,7 @@ body {
} }
.container { .container {
width: 98%; width: 100%;
margin: auto; margin: auto;
overflow: hidden; overflow: hidden;
padding: 0; /* Remove padding */ padding: 0; /* Remove padding */
@@ -17,10 +17,11 @@ body {
.login-page { .login-page {
display: flex; display: flex;
align-items: center; align-items: center; /* Vertically center the content */
justify-content: center; justify-content: space-between; /* Space between the logo and the form container */
height: 100vh; height: 100vh; /* Full height of the viewport */
background-color: #f4f4f9; background-color: #f4f4f9;
padding: 0 20px; /* Add padding to the sides */
} }
header { header {
@@ -92,12 +93,13 @@ header {
} }
.form-container { .form-container {
width: 600px; /* Set a fixed width for the login container */ width: 600px; /* Fixed width for the login container */
background: #fff; background: #fff;
padding: 15px 30px 15px 15px; /* Add 30px padding to the right */ padding: 15px 30px; /* Add padding inside the container */
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 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 { .form-container h2 {
@@ -228,18 +230,17 @@ body.dark-mode .card {
/* Common card styles */ /* Common card styles */
.card { .card {
width: 400px; /* Fixed width */ width: 600px;
height: 150px; /* Fixed height */ background: #fff;
border-radius: 5px; border-radius: 5px;
padding: 20px; padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin: 20px auto; /* Center the card horizontally */ margin: 20px auto;
text-align: center; text-align: center;
transition: background-color 0.3s ease, color 0.3s ease, border 0.3s ease;
} }
.card h3 { .card h3 {
margin-bottom: 10px; margin-bottom: 20px;
font-size: 1.5em; font-size: 1.5em;
} }
@@ -261,4 +262,134 @@ body.dark-mode .card {
.card .btn:hover { .card .btn:hover {
background-color: #0056b3; 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;
} }

View File

@@ -10,10 +10,10 @@
<div class="form-container"> <div class="form-container">
<h2>Login</h2> <h2>Login</h2>
<form method="POST"> <form method="POST">
<label for="email">Email:</label> <label for="username">Username:</label>
<input type="email" name="email" required> <input type="text" id="username" name="username" required>
<label for="password">Password:</label> <label for="password">Password:</label>
<input type="password" name="password" required> <input type="password" id="password" name="password" required>
<button type="submit">Login</button> <button type="submit">Login</button>
</form> </form>
</div> </div>

View File

@@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block title %}Quality Module{% endblock %}
{% block content %}
<h2>Quality Module</h2>
<p>Welcome to the Quality Module.</p>
{% endblock %}

View File

@@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block title %}Scan Module{% endblock %}
{% block content %}
<h2>Scan Module</h2>
<p>Welcome to the Scan Module.</p>
{% endblock %}

View File

@@ -3,6 +3,77 @@
{% block title %}Settings{% endblock %} {% block title %}Settings{% endblock %}
{% block content %} {% block content %}
<h2>Settings Page</h2> <div class="card">
<p>This is the settings page. Add your settings here.</p> <h3>Manage Users</h3>
<ul class="user-list">
{% for user in users %}
<li data-user-id="{{ user.id }}">
<span class="user-name">{{ user.username }}</span>
<span class="user-role">Role: {{ user.role }}</span>
<button class="btn edit-btn">Edit Rights</button>
<button class="btn delete-btn">Delete User</button>
</li>
{% endfor %}
</ul>
<button id="create-user-btn" class="btn create-btn">Create User</button>
</div>
<!-- Popup for creating a new user -->
<div id="create-user-popup" class="popup">
<div class="popup-content">
<h3>Create User</h3>
<form id="create-user-form" method="POST" action="{{ url_for('main.create_user') }}">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<label for="role">Role:</label>
<select id="role" name="role" required>
<option value="superadmin">Superadmin</option>
<option value="administrator">Administrator</option>
<option value="quality">Quality</option>
<option value="warehouse">Warehouse</option>
<option value="scan">Scan</option>
</select>
<button type="submit" class="btn">Create</button>
<button type="button" id="close-popup-btn" class="btn cancel-btn">Cancel</button>
</form>
</div>
</div>
<!-- Popup for editing a user -->
<div id="edit-user-popup" class="popup">
<div class="popup-content">
<h3>Edit User</h3>
<form id="edit-user-form" method="POST" action="{{ url_for('main.edit_user') }}">
<input type="hidden" id="edit-user-id" name="user_id">
<label for="edit-username">Username:</label>
<input type="text" id="edit-username" name="username" readonly>
<label for="edit-password">New Password:</label>
<input type="password" id="edit-password" name="password">
<label for="edit-role">Role:</label>
<select id="edit-role" name="role" required>
<option value="superadmin">Superadmin</option>
<option value="administrator">Administrator</option>
<option value="quality">Quality</option>
<option value="warehouse">Warehouse</option>
<option value="scan">Scan</option>
</select>
<button type="submit" class="btn">Update</button>
<button type="button" id="close-edit-popup-btn" class="btn cancel-btn">Cancel</button>
</form>
</div>
</div>
<!-- Popup for confirming user deletion -->
<div id="delete-user-popup" class="popup">
<div class="popup-content">
<h3>Do you really want to delete the user <span id="delete-username"></span>?</h3>
<form id="delete-user-form" method="POST" action="{{ url_for('main.delete_user') }}">
<input type="hidden" id="delete-user-id" name="user_id">
<button type="submit" class="btn delete-confirm-btn">Yes</button>
<button type="button" id="close-delete-popup-btn" class="btn cancel-btn">No</button>
</form>
</div>
</div>
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block title %}Warehouse Module{% endblock %}
{% block content %}
<h2>Warehouse Module</h2>
<p>Welcome to the Warehouse Module.</p>
{% endblock %}

BIN
py_app/instance/users.db Normal file

Binary file not shown.

View File

@@ -1,4 +1,5 @@
Flask==2.2.2 Flask==2.2.2
Flask-SSLify==0.1.5 Flask-SSLify==0.1.5
Werkzeug==2.2.2 Werkzeug==2.2.2
gunicorn==20.1.0 gunicorn==20.1.0
flask-sqlalchemy==2.5.1

22
py_app/seed.py Normal file
View File

@@ -0,0 +1,22 @@
from app import create_app, db
from app.models import User
app = create_app()
with app.app_context():
# Add default users
users = [
User(username='superadmin', password='superadmin123', role='superadmin'),
User(username='admin', password='admin123', role='administrator'),
User(username='quality_user', password='quality123', role='quality'),
User(username='warehouse_user', password='warehouse123', role='warehouse'),
User(username='scan_user', password='scan123', role='scan'),
]
# Add users to the database
for user in users:
if not User.query.filter_by(username=user.username).first():
db.session.add(user)
db.session.commit()
print("Database seeded with default users.")