deleted some mistakes
This commit is contained in:
parent
4ecec74da0
commit
482d2e28f9
5 changed files with 0 additions and 222 deletions
|
|
@ -1,34 +0,0 @@
|
||||||
"""
|
|
||||||
WTForms definitions for authentication and inspection CRUD.
|
|
||||||
"""
|
|
||||||
from flask_wtf import FlaskForm
|
|
||||||
from wtforms import StringField, PasswordField, TextAreaField, BooleanField, SubmitField, FileField
|
|
||||||
from wtforms.validators import DataRequired, Length, EqualTo, ValidationError
|
|
||||||
from flask_wtf.file import FileAllowed, FileRequired
|
|
||||||
from config import Config
|
|
||||||
|
|
||||||
class LoginForm(FlaskForm):
|
|
||||||
username = StringField("Username", validators=[DataRequired(), Length(max=64)])
|
|
||||||
password = PasswordField("Password", validators=[DataRequired()])
|
|
||||||
submit = SubmitField("Login")
|
|
||||||
|
|
||||||
class RegisterForm(FlaskForm):
|
|
||||||
username = StringField("Username", validators=[DataRequired(), Length(max=64)])
|
|
||||||
password = PasswordField("Password", validators=[DataRequired(), Length(min=8)])
|
|
||||||
confirm = PasswordField("Confirm Password", validators=[DataRequired(), EqualTo('password')])
|
|
||||||
submit = SubmitField("Register")
|
|
||||||
|
|
||||||
class InspectionForm(FlaskForm):
|
|
||||||
title = StringField("Title", validators=[DataRequired(), Length(max=128)])
|
|
||||||
description = TextAreaField("Description")
|
|
||||||
remark_a = BooleanField("Remark A")
|
|
||||||
remark_b = BooleanField("Remark B")
|
|
||||||
remark_c = BooleanField("Remark C")
|
|
||||||
photos = FileField("Photos", validators=[FileAllowed(list(Config.ALLOWED_EXTENSIONS), "Images only!")], render_kw={"multiple": True})
|
|
||||||
submit = SubmitField("Save")
|
|
||||||
|
|
||||||
class PasswordChangeForm(FlaskForm):
|
|
||||||
current_password = PasswordField("Current Password", validators=[DataRequired()])
|
|
||||||
new_password = PasswordField("New Password", validators=[DataRequired(), Length(min=8)])
|
|
||||||
confirm_new = PasswordField("Confirm New Password", validators=[DataRequired(), EqualTo('new_password')])
|
|
||||||
submit = SubmitField("Change Password")
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
Flask
|
|
||||||
Flask-Login
|
|
||||||
Flask-WTF
|
|
||||||
Flask-SQLAlchemy
|
|
||||||
WeasyPrint
|
|
||||||
Werkzeug
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
"""
|
|
||||||
Flask blueprints for authentication and main inspection functionality.
|
|
||||||
"""
|
|
||||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, current_app, send_file
|
|
||||||
from flask_login import login_user, logout_user, current_user, login_required
|
|
||||||
from werkzeug.utils import secure_filename
|
|
||||||
import os
|
|
||||||
import io
|
|
||||||
|
|
||||||
from models import User, Inspection, Photo, db, load_user
|
|
||||||
from forms import LoginForm, RegisterForm, InspectionForm, PasswordChangeForm
|
|
||||||
from utils import save_photo, generate_pdf
|
|
||||||
|
|
||||||
# Flask-Login requires user loader
|
|
||||||
@login_manager.user_loader
|
|
||||||
def load_user_id(user_id):
|
|
||||||
return load_user(user_id)
|
|
||||||
|
|
||||||
# Auth blueprint
|
|
||||||
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')
|
|
||||||
|
|
||||||
@auth_bp.route('/login', methods=['GET', 'POST'])
|
|
||||||
def login():
|
|
||||||
form = LoginForm()
|
|
||||||
if form.validate_on_submit():
|
|
||||||
user = User.query.filter_by(username=form.username.data).first()
|
|
||||||
if user and user.check_password(form.password.data):
|
|
||||||
login_user(user)
|
|
||||||
next_page = request.args.get('next') or url_for('main.index')
|
|
||||||
return redirect(next_page)
|
|
||||||
flash('Invalid username or password', 'danger')
|
|
||||||
return render_template('login.html', form=form)
|
|
||||||
|
|
||||||
@auth_bp.route('/logout')
|
|
||||||
@login_required
|
|
||||||
def logout():
|
|
||||||
logout_user()
|
|
||||||
return redirect(url_for('auth.login'))
|
|
||||||
|
|
||||||
@auth_bp.route('/register', methods=['GET', 'POST'])
|
|
||||||
def register():
|
|
||||||
form = RegisterForm()
|
|
||||||
if form.validate_on_submit():
|
|
||||||
if User.query.filter_by(username=form.username.data).first():
|
|
||||||
flash('Username already exists', 'warning')
|
|
||||||
else:
|
|
||||||
user = User(username=form.username.data)
|
|
||||||
user.set_password(form.password.data)
|
|
||||||
db.session.add(user)
|
|
||||||
db.session.commit()
|
|
||||||
flash('Registration successful. Please log in.', 'success')
|
|
||||||
return redirect(url_for('auth.login'))
|
|
||||||
return render_template('register.html', form=form)
|
|
||||||
|
|
||||||
# Main blueprint for inspection CRUD
|
|
||||||
main_bp = Blueprint('main', __name__)
|
|
||||||
|
|
||||||
@main_bp.route('/')
|
|
||||||
def index():
|
|
||||||
inspections = Inspection.query.order_by(Inspection.created_at.desc()).all()
|
|
||||||
return render_template('inspections.html', inspections=inspections)
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/new', methods=['GET', 'POST'])
|
|
||||||
@login_required
|
|
||||||
def create_inspection():
|
|
||||||
form = InspectionForm()
|
|
||||||
if form.validate_on_submit():
|
|
||||||
insp = Inspection(
|
|
||||||
title=form.title.data,
|
|
||||||
description=form.description.data,
|
|
||||||
remark_a=form.remark_a.data,
|
|
||||||
remark_b=form.remark_b.data,
|
|
||||||
remark_c=form.remark_c.data,
|
|
||||||
created_by=current_user.id
|
|
||||||
)
|
|
||||||
db.session.add(insp)
|
|
||||||
db.session.commit()
|
|
||||||
# Handle photos
|
|
||||||
files = request.files.getlist('photos')
|
|
||||||
for f in files:
|
|
||||||
if f and f.filename:
|
|
||||||
try:
|
|
||||||
filename = save_photo(f)
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
photo = Photo(filename=filename, inspection_id=insp.id)
|
|
||||||
db.session.add(photo)
|
|
||||||
db.session.commit()
|
|
||||||
flash('Inspection created', 'success')
|
|
||||||
return redirect(url_for('main.detail', inspection_id=insp.id))
|
|
||||||
return render_template('inspection_form.html', form=form, action='Create')
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/<int:inspection_id>')
|
|
||||||
@login_required
|
|
||||||
def detail(inspection_id):
|
|
||||||
insp = Inspection.query.get_or_404(inspection_id)
|
|
||||||
return render_template('inspection_detail.html', inspection=insp)
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/<int:inspection_id>/edit', methods=['GET', 'POST'])
|
|
||||||
@login_required
|
|
||||||
def edit_inspection(inspection_id):
|
|
||||||
insp = Inspection.query.get_or_404(inspection_id)
|
|
||||||
form = InspectionForm(obj=insp)
|
|
||||||
if form.validate_on_submit():
|
|
||||||
insp.title = form.title.data
|
|
||||||
insp.description = form.description.data
|
|
||||||
insp.remark_a = form.remark_a.data
|
|
||||||
insp.remark_b = form.remark_b.data
|
|
||||||
insp.remark_c = form.remark_c.data
|
|
||||||
# Handle new photos
|
|
||||||
files = request.files.getlist('photos')
|
|
||||||
for f in files:
|
|
||||||
if f and f.filename:
|
|
||||||
try:
|
|
||||||
filename = save_photo(f)
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
photo = Photo(filename=filename, inspection_id=insp.id)
|
|
||||||
db.session.add(photo)
|
|
||||||
db.session.commit()
|
|
||||||
flash('Inspection updated', 'success')
|
|
||||||
return redirect(url_for('main.detail', inspection_id=insp.id))
|
|
||||||
return render_template('inspection_form.html', form=form, action='Edit')
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/<int:inspection_id>/delete', methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def delete_inspection(inspection_id):
|
|
||||||
insp = Inspection.query.get_or_404(inspection_id)
|
|
||||||
db.session.delete(insp)
|
|
||||||
db.session.commit()
|
|
||||||
flash('Inspection deleted', 'info')
|
|
||||||
return redirect(url_for('main.index'))
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/<int:inspection_id>/close', methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def close_inspection(inspection_id):
|
|
||||||
insp = Inspection.query.get_or_404(inspection_id)
|
|
||||||
insp.closed_at = datetime.utcnow()
|
|
||||||
db.session.commit()
|
|
||||||
flash('Inspection closed', 'success')
|
|
||||||
return redirect(url_for('main.detail', inspection_id=insp.id))
|
|
||||||
|
|
||||||
@main_bp.route('/inspection/<int:inspection_id>/pdf')
|
|
||||||
@login_required
|
|
||||||
def download_pdf(inspection_id):
|
|
||||||
insp = Inspection.query.get_or_404(inspection_id)
|
|
||||||
output_path = os.path.join(Config.PDF_FOLDER, f'inspection_{insp.id}.pdf')
|
|
||||||
generate_pdf('pdf_template.html', {'inspection': insp}, output_path)
|
|
||||||
return send_file(output_path, as_attachment=True, download_name=f'inspection_{insp.id}.pdf')
|
|
||||||
|
|
||||||
"
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<title>{% block title %}Inspection App{% endblock %}</title>
|
|
||||||
<link rel="stylesheet" href="/static/style.css">
|
|
||||||
<nav>
|
|
||||||
<a href="{{ url_for('main.index') }}">Home</a>
|
|
||||||
{% if current_user.is_authenticated %}
|
|
||||||
<a href="{{ url_for('auth.logout') }}">Logout</a>
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ url_for('auth.login') }}">Login</a>
|
|
||||||
{% endif %}
|
|
||||||
</nav>
|
|
||||||
<div class="container">
|
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
||||||
{% if messages %}
|
|
||||||
{% for category, msg in messages %}
|
|
||||||
<div class="alert {{ category }}">{{ msg }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
{% extends "layout.html" %}
|
|
||||||
{% block title %}Login{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h2>Login</h2>
|
|
||||||
<form method="post">{{ form.hidden_tag() }}
|
|
||||||
<div>{{ form.username.label }} {{ form.username() }}</div>
|
|
||||||
<div>{{ form.password.label }} {{ form.password() }}</div>
|
|
||||||
<div>{{ form.submit() }}</div>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
Loading…
Reference in a new issue