mirror of
				https://github.com/StefBuwalda/ProjectIOT.git
				synced 2025-10-30 19:29:57 +00:00 
			
		
		
		
	changed files on the frontend
This commit is contained in:
		
							
								
								
									
										3
									
								
								AT_frontend/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								AT_frontend/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +1 @@ | |||||||
| .venv/ | .venvs/ | ||||||
| __pychache__/ |  | ||||||
| @@ -1,152 +1,35 @@ | |||||||
| from flask import Flask, render_template, request, redirect, url_for, flash, session | from flask import Flask, render_template, session, redirect, url_for, session | ||||||
| from flask_wtf import FlaskForm | from flask_wtf import FlaskForm | ||||||
| from wtforms import StringField, PasswordField, BooleanField, SubmitField | from wtforms import (StringField, BooleanField, | ||||||
|  |                                   RadioField, SelectField, | ||||||
|  |                                   TextAreaField, SubmitField) | ||||||
| from wtforms.validators import DataRequired | from wtforms.validators import DataRequired | ||||||
| from functools import wraps |  | ||||||
| import os |  | ||||||
| from flask_sqlalchemy import SQLAlchemy |  | ||||||
| from datetime import datetime |  | ||||||
|  |  | ||||||
| app = Flask(__name__) | app = Flask(__name__) | ||||||
| app.config['SECRET_KEY'] = 'your-secret-key'  # Change this to a random string |  | ||||||
|  |  | ||||||
| # Database configuration - update with your friend's database info | app.config['SECRET_KEY'] = 'mijngeheimesleutel' | ||||||
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///logs.db'  # Change this to match your friend's DB |  | ||||||
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |  | ||||||
| db = SQLAlchemy(app) |  | ||||||
|  |  | ||||||
| # Simple log model - adjust to match your friend's database structure | class InfoForm(FlaskForm): | ||||||
| class Log(db.Model): |  | ||||||
|     id = db.Column(db.Integer, primary_key=True) |  | ||||||
|     action = db.Column(db.String(100), nullable=False) |  | ||||||
|     timestamp = db.Column(db.DateTime, default=datetime.utcnow) |  | ||||||
|      |  | ||||||
|     def __repr__(self): |  | ||||||
|         return f"Log('{self.action}', '{self.timestamp}')" |  | ||||||
|  |  | ||||||
| # Keep your existing user dictionary for authentication |     naam = StringField('Wat is je naam?',validators=[DataRequired()]) | ||||||
| users = { |     vrouw  = BooleanField("Ben je een vrouw?") | ||||||
|     "admin": {"password": "admin123", "role": "admin"}, |     instrument = RadioField('Welk instrument wil je leren bespelen?',   choices=[('ins_een','Gitaar'),('ins_twee','Drums')]) | ||||||
|     "user": {"password": "user123", "role": "user"} |     plaats = SelectField(u'Welke locatie heeft de voorkeur?', | ||||||
| } |              choices=[('as', 'Assen'), ('dr', 'Drachten'), ('gr', 'Groningen')]) | ||||||
|  |     feedback = TextAreaField() | ||||||
|  |     submit = SubmitField('Verzend') | ||||||
|  |  | ||||||
| # Add a function to create a new log entry | @app.route('/', methods=['GET', 'POST']) | ||||||
| def add_log(action): |  | ||||||
|     log = Log(action=action) |  | ||||||
|     db.session.add(log) |  | ||||||
|     db.session.commit() |  | ||||||
|  |  | ||||||
| class LoginForm(FlaskForm): |  | ||||||
|     username = StringField('Username', validators=[DataRequired()]) |  | ||||||
|     password = PasswordField('Password', validators=[DataRequired()]) |  | ||||||
|     remember = BooleanField('Remember Me') |  | ||||||
|  |  | ||||||
| class GateControlForm(FlaskForm): |  | ||||||
|     open_gate = SubmitField('Open Gate') |  | ||||||
|     close_gate = SubmitField('Close Gate') |  | ||||||
|     check_camera = SubmitField('Check Camera') |  | ||||||
|     debug_mode = BooleanField('Debug Mode') |  | ||||||
|  |  | ||||||
| def login_required(f): |  | ||||||
|     @wraps(f) |  | ||||||
|     def decorated_function(*args, **kwargs): |  | ||||||
|         if 'logged_in' not in session: |  | ||||||
|             return redirect(url_for('login')) |  | ||||||
|         return f(*args, **kwargs) |  | ||||||
|     return decorated_function |  | ||||||
|  |  | ||||||
| def admin_required(f): |  | ||||||
|     @wraps(f) |  | ||||||
|     def decorated_function(*args, **kwargs): |  | ||||||
|         if 'role' not in session or session['role'] != 'admin': |  | ||||||
|             flash('You need to be an admin to access this page.') |  | ||||||
|             return redirect(url_for('login')) |  | ||||||
|         return f(*args, **kwargs) |  | ||||||
|     return decorated_function |  | ||||||
|  |  | ||||||
| @app.route('/') |  | ||||||
| def index(): | def index(): | ||||||
|     if 'logged_in' in session: |  | ||||||
|         if session['role'] == 'admin': |  | ||||||
|             return redirect(url_for('dashboard')) |  | ||||||
|         return redirect(url_for('user_page')) |  | ||||||
|     return redirect(url_for('login')) |  | ||||||
|  |  | ||||||
| @app.route('/login', methods=['GET', 'POST']) |     form = InfoForm() | ||||||
| def login(): |  | ||||||
|     form = LoginForm() |  | ||||||
|     error = None |  | ||||||
|      |  | ||||||
|     if request.method == 'POST': |  | ||||||
|         username = request.form['username'] |  | ||||||
|         password = request.form['password'] |  | ||||||
|          |  | ||||||
|         if username in users and users[username]['password'] == password: |  | ||||||
|             session['logged_in'] = True |  | ||||||
|             session['username'] = username |  | ||||||
|             session['role'] = users[username]['role'] |  | ||||||
|              |  | ||||||
|             # Log the login action |  | ||||||
|             add_log(f"User {username} logged in") |  | ||||||
|              |  | ||||||
|             if users[username]['role'] == 'admin': |  | ||||||
|                 return redirect(url_for('dashboard')) |  | ||||||
|             else: |  | ||||||
|                 return redirect(url_for('user_page')) |  | ||||||
|         else: |  | ||||||
|             # Log the failed login attempt |  | ||||||
|             add_log(f"Failed login attempt for user {username}") |  | ||||||
|             error = 'Invalid credentials. Please try again.' |  | ||||||
|      |  | ||||||
|     return render_template('inlog.html', form=form, error=error) |  | ||||||
|  |  | ||||||
| @app.route('/dashboard', methods=['GET', 'POST']) |  | ||||||
| @login_required |  | ||||||
| @admin_required |  | ||||||
| def dashboard(): |  | ||||||
|     form = GateControlForm() |  | ||||||
|     gate_status = "Closed" |  | ||||||
|     camera_status = "Inactive" |  | ||||||
|     debug_mode = False |  | ||||||
|      |  | ||||||
|     # Get the most recent logs to display |  | ||||||
|     recent_logs = Log.query.order_by(Log.timestamp.desc()).limit(10).all() |  | ||||||
|      |  | ||||||
|     if form.validate_on_submit(): |     if form.validate_on_submit(): | ||||||
|         if form.open_gate.data: |  | ||||||
|             gate_status = "Open" |  | ||||||
|             add_log("Gate opened by " + session['username']) |  | ||||||
|         elif form.close_gate.data: |  | ||||||
|             gate_status = "Closed" |  | ||||||
|             add_log("Gate closed by " + session['username']) |  | ||||||
|         elif form.check_camera.data: |  | ||||||
|             camera_status = "Active" |  | ||||||
|             add_log("Camera checked by " + session['username']) |  | ||||||
|          |  | ||||||
|         debug_mode = form.debug_mode.data |  | ||||||
|         if debug_mode: |  | ||||||
|             add_log("Debug mode enabled by " + session['username']) |  | ||||||
|      |  | ||||||
|     return render_template('dashboard.html', form=form, gate_status=gate_status,  |  | ||||||
|                            camera_status=camera_status, debug_mode=debug_mode, |  | ||||||
|                            recent_logs=recent_logs) |  | ||||||
|  |  | ||||||
| @app.route('/user') |         session['naam'] = form.username.data | ||||||
| @login_required |         session['password'] = form.password.data | ||||||
| def user_page(): |  | ||||||
|     add_log(f"User {session['username']} accessed user page") |  | ||||||
|     return "Regular user page - Access restricted" |  | ||||||
|  |  | ||||||
| @app.route('/logout') |         return render_template('dashboard.html') | ||||||
| def logout(): |     return render_template('login.html', form=form) | ||||||
|     if 'username' in session: |  | ||||||
|         add_log(f"User {session['username']} logged out") |  | ||||||
|     session.clear() |  | ||||||
|     return redirect(url_for('login')) |  | ||||||
|  |  | ||||||
| # Initialize database |  | ||||||
| with app.app_context(): |  | ||||||
|     db.create_all() |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     app.run(debug=True) |     app.run(debug=True) | ||||||
							
								
								
									
										
											BIN
										
									
								
								AT_frontend/static/images/car.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AT_frontend/static/images/car.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								AT_frontend/static/images/logo-light.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								AT_frontend/static/images/logo-light.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 8.6 KiB | 
| @@ -1,68 +1,18 @@ | |||||||
| {%extends 'base.html' %} | <!DOCTYPE html> | ||||||
| {% block content %} | <html lang="en"> | ||||||
|                 <div class="row"> | <head> | ||||||
|                     <div class="col-md-4"> |     <meta charset="UTF-8"> | ||||||
|                         <div class="card mb-4"> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|                             <div class="card-body"> |     <title>Document</title> | ||||||
|                                 <h5>Gate Control Dashboard</h5> | </head> | ||||||
|                                 <form method="POST"> | <body> | ||||||
|                                     {{ form.hidden_tag() }} |     <h1>Bedankt voor de moeite. <br>Dit zijn de ingevulde gegevens:</h1> | ||||||
|                                     <div class="d-grid gap-2 mb-3"> | <ul> | ||||||
|                                         {{ form.open_gate(class="btn btn-dark") }}  |     <li>Naam: {{ session['naam'] }}</li> | ||||||
|                                     </div> |     <li>Geslacht: {{ session['geslacht'] }}</li> | ||||||
|                                     <div class="d-grid gap-2 mb-3"> |     <li>Instrument: {{ session['instrument'] }}</li> | ||||||
|                                         {{ form.close_gate(class="btn btn-dark") }} |     <li>Plaats: {{ session['plaats'] }}</li> | ||||||
|                                     </div> |     <li>Feedback: {{ session['feedback'] }}</li> | ||||||
|                                     <div class="d-grid gap-2 mb-3"> | </ul> | ||||||
|                                         {{ form.check_camera(class="btn btn-dark") }} | </body> | ||||||
|                                     </div> | </html> | ||||||
|                                     <div class="mb-3"> |  | ||||||
|                                         {{ form.debug_mode() }}  |  | ||||||
|                                         <label for="{{ form.debug_mode.id }}">Enable Debug Mode</label> |  | ||||||
|                                     </div> |  | ||||||
|                                     <div class="d-grid"> |  | ||||||
|                                         <button type="submit" class="btn btn-dark">Submit</button> |  | ||||||
|                                     </div> |  | ||||||
|                                 </form> |  | ||||||
|                                 <h6>Gate Status: {{ gate_status }}</h6> |  | ||||||
|                                 <h6>Camera Status: {{ camera_status }}</h6> |  | ||||||
|                                 {% if debug_mode %} |  | ||||||
|                                     <h7>Debug Mode is Enabled</h7> |  | ||||||
|                                 {% endif %} |  | ||||||
|                             </div> |  | ||||||
|                         </div> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="col-md-4"> |  | ||||||
|                         <div class="card mb-4"> |  | ||||||
|                             <div class="card-body"> |  | ||||||
|                                 <h5 class="card-title">System Logs</h5> |  | ||||||
|                                 <div class="log-container" style="max-height: 250px; overflow-y: auto;"> |  | ||||||
|                                     <table class="table table-sm table-hover"> |  | ||||||
|                                         <thead> |  | ||||||
|                                             <tr> |  | ||||||
|                                                 <th scope="col">Time</th> |  | ||||||
|                                                 <th scope="col">Action</th> |  | ||||||
|                                                 <th scope="col">Status</th> |  | ||||||
|                                             </tr> |  | ||||||
|                                         </thead> |  | ||||||
|                                         <tbody> |  | ||||||
|                                             {% for log in recent_logs %} |  | ||||||
|                                             <tr> |  | ||||||
|                                                 <td><small>{{ log.timestamp.strftime('%H:%M:%S') }}</small></td> |  | ||||||
|                                                 <td><small>{{ log.action }}</small></td> |  | ||||||
|                                                 <td> |  | ||||||
|                                                     <span class="badge {% if log.status == 'success' %}bg-success{% elif log.status == 'warning' %}bg-warning{% elif log.status == 'error' %}bg-danger{% else %}bg-secondary{% endif %}"> |  | ||||||
|                                                         {{ log.status }} |  | ||||||
|                                                     </span> |  | ||||||
|                                                 </td> |  | ||||||
|                                             </tr> |  | ||||||
|                                             {% endfor %} |  | ||||||
|                                         </tbody> |  | ||||||
|                                     </table> |  | ||||||
|                                 </div> |  | ||||||
|                             </div> |  | ||||||
|                         </div> |  | ||||||
|                     </div> |  | ||||||
|                      |  | ||||||
| </html> |  | ||||||
| {% endblock %} |  | ||||||
							
								
								
									
										75
									
								
								AT_frontend/templates/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								AT_frontend/templates/login.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  |     <meta charset="UTF-8"> | ||||||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  |     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-SgOJa3DmI69IUzQ2PVdRZhwQ+dy64/BUtbMJw1MZ8t5HZApcHrRKUc4W0kG879m7" crossorigin="anonymous"> | ||||||
|  |     <title>Login</title> | ||||||
|  |     <style> | ||||||
|  |         .rounded-input { | ||||||
|  |             border-radius: 20px;  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .split-background { | ||||||
|  |             position: fixed; | ||||||
|  |             top: 0; | ||||||
|  |             left: 0; | ||||||
|  |             width: 100%; | ||||||
|  |             height: 50vh; | ||||||
|  |             background-color: #424D66; | ||||||
|  |             z-index: -1; | ||||||
|  |         } | ||||||
|  |         @keyframes moveLeftRight { | ||||||
|  |             0% { | ||||||
|  |                 transform: translateX(0);  | ||||||
|  |             } | ||||||
|  |             100% { | ||||||
|  |                 transform: translateX(1366px);  | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         .logo { | ||||||
|  |             margin-top: 70px; | ||||||
|  |             width: 770px;  | ||||||
|  |             height: auto; | ||||||
|  |         } | ||||||
|  |         .car-image-container { | ||||||
|  |             position: fixed; | ||||||
|  |             bottom: 33px; | ||||||
|  |         } | ||||||
|  |         .animate { | ||||||
|  |             animation: moveLeftRight 15s infinite alternate; | ||||||
|  |         } | ||||||
|  |     </style> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div class="split-background"> | ||||||
|  |     <div class="container-fluid text-center"> | ||||||
|  |         <img src="../static/images/logo-light.png" alt="Logo" class="logo" class="img-fluid mt-5"> | ||||||
|  |             </div> | ||||||
|  |                 </div> | ||||||
|  |                     <div class="container d-flex justify-content-center align-items-center" style="min-height: 100vh;"> | ||||||
|  |                         <div class="col-md-6 col-lg-4"> | ||||||
|  |                             <form method="POST" class="p-5 border rounded-input shadow-sm bg-white bg-opacity-75"> | ||||||
|  |                                 <div class=" p-4 border rounded-input shadow-sm bg-white"> | ||||||
|  |                                     <label for="username" class="form-label text-center w-100">Username</label> | ||||||
|  |                                             <input type="text" class="form-control rounded-input" id="username" name="username" required> | ||||||
|  |                                                 <label for="password" class="form-label text-center w-100">Password</label> | ||||||
|  |                                                     <input type="password" class="form-control rounded-input" id="password" name="password" required> | ||||||
|  |                                                 <br> | ||||||
|  |                                             <div class="d-grid"> | ||||||
|  |                                         <button type="submit" class="btn btn-dark rounded-input px-4 mx-auto w-50">Sign in</button> | ||||||
|  |                                         </div> | ||||||
|  |                                     </div> | ||||||
|  |                                 </form> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="car-image-container"> | ||||||
|  |                         <img src="../static/images/car.png" alt="Moving Image" class="animate"> | ||||||
|  |                         </div> | ||||||
|  |                     <footer class="py-3 bg-dark text-white fixed-bottom""> | ||||||
|  |                 <div class="container text-center"> | ||||||
|  |             <span class="text-muted"> </span> | ||||||
|  |         </div> | ||||||
|  |     </footer> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
		Reference in New Issue
	
	Block a user
	 Anh-Thy04
					Anh-Thy04