pre-bootstrap

This commit is contained in:
Vadim Likholetov 2023-10-30 16:48:00 +02:00
parent 29ef64a0f3
commit 45c4070034
13 changed files with 390 additions and 0 deletions

9
admin.py Normal file
View File

@ -0,0 +1,9 @@
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from app import app, db
from models import User, SARCall, SARCategory
admin = Admin(app, name='SAR Admin', template_mode='bootstrap3')
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(SARCall, db.session))
admin.add_view(ModelView(SARCategory, db.session))

14
app.py
View File

@ -1,7 +1,21 @@
from flask import Flask from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
app = Flask(__name__) app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
db = SQLAlchemy(app)
migrate = Migrate(app,db)
login_manager = LoginManager(app)
import models
import admin
import login
import sar_calls
import dashboard
@app.route('/') @app.route('/')
def hello_world(): # put application's code here def hello_world(): # put application's code here

11
create_db.py Normal file
View File

@ -0,0 +1,11 @@
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
db = SQLAlchemy(app)
from models import User, SARCall, SARCategory
if __name__ == '__main__':
db.create_all()

8
dashboard.py Normal file
View File

@ -0,0 +1,8 @@
from app import app
from flask import render_template
from flask_login import login_required, current_user
@app.route('/dashboard')
@login_required
def dashboard():
return render_template('dashboard.html', name=current_user.full_name)

39
login.py Normal file
View File

@ -0,0 +1,39 @@
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from app import app, db, login_manager
from models import User
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user and user.password == password:
login_user(user)
return redirect(url_for('dashboard'))
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
email = request.form.get('email')
full_name = request.form.get('full_name')
phone_number = request.form.get('phone_number')
new_user = User(username=username, password=password, email=email, full_name=full_name, phone_number=phone_number)
db.session.add(new_user)
db.session.commit()
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))

26
models.py Normal file
View File

@ -0,0 +1,26 @@
from flask_login import UserMixin
from app import db
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
full_name = db.Column(db.String(300), nullable=False)
email = db.Column(db.String(150), unique=True, nullable=False)
phone_number = db.Column(db.String(50), nullable=True)
password = db.Column(db.String(50))
class SARCall(db.Model):
id = db.Column(db.Integer, primary_key=True)
start_date = db.Column(db.DateTime, nullable=False)
finish_date = db.Column(db.DateTime, nullable=False)
category = db.Column(db.String(150), nullable=False)
latitude = db.Column(db.Float, nullable=False)
longitude = db.Column(db.Float, nullable=False)
search_manager_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
gpx_data = db.Column(db.Text, nullable=True) # This will store GPX data as a text
class SARCategory(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(150), unique=True, nullable=False)

64
sar_calls.py Normal file
View File

@ -0,0 +1,64 @@
from app import app, db
from flask import request, redirect, flash, render_template, url_for
from flask_login import login_required, current_user
from dateutil import parser
from models import SARCall
@app.route('/create_sar', methods=['GET', 'POST'])
@login_required
def create_sar():
if request.method == 'POST':
start_date = parser.parse(request.form.get('start_date'))
finish_date = parser.parse(request.form.get('finish_date'))
category = request.form.get('category')
latitude = request.form.get('latitude')
longitude = request.form.get('longitude')
gpx_data = request.form.get('gpx_data')
new_sar_call = SARCall(
start_date=start_date,
finish_date=finish_date,
category=category,
latitude=latitude,
longitude=longitude,
search_manager_id=current_user.id,
gpx_data=gpx_data
)
db.session.add(new_sar_call)
db.session.commit()
flash('SAR call created successfully!', 'success')
return redirect(url_for('dashboard'))
return render_template('create_sar.html')
@app.route('/list_sar')
@login_required
def list_sar():
sar_calls = SARCall.query.all()
return render_template('list_sar.html', sar_calls=sar_calls)
@app.route('/edit_sar/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_sar(id):
sar_call = SARCall.query.get(id)
if request.method == 'POST':
sar_call.start_date = request.form.get('start_date')
sar_call.finish_date = request.form.get('finish_date')
sar_call.category = request.form.get('category')
sar_call.latitude = request.form.get('latitude')
sar_call.longitude = request.form.get('longitude')
sar_call.gpx_data = request.form.get('gpx_data')
db.session.commit()
flash('SAR call updated successfully!', 'success')
return redirect(url_for('list_sar'))
return render_template('edit_sar.html', sar_call=sar_call)
@app.route('/delete_sar/<int:id>')
@login_required
def delete_sar(id):
sar_call = SARCall.query.get(id)
db.session.delete(sar_call)
db.session.commit()
flash('SAR call deleted successfully!', 'success')
return redirect(url_for('list_sar'))

70
templates/create_sar.html Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<title>Create SAR Call</title>
</head>
<body>
<h2>Create SAR Call</h2>
<form action="/create_sar" method="post">
<div>
<label for="start_date">Start Date:</label>
<input type="date" name="start_date" required>
</div>
<div>
<label for="finish_date">Finish Date:</label>
<input type="date" name="finish_date" required>
</div>
<div>
<label for="category">Category:</label>
<input type="text" name="category" required>
</div>
<div>
<label for="latitude">Latitude:</label>
<input type="text" name="latitude" required>
</div>
<div>
<label for="longitude">Longitude:</label>
<input type="text" name="longitude" required>
</div>
<div>
<label for="gpx_data">GPX Data:</label>
<textarea name="gpx_data"></textarea>
</div>
<div>
<input type="submit" value="Create">
</div>
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
var map = L.map('map').setView([51.505, -0.09], 13); // Default to London, adjust as needed
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var marker;
map.on('click', function (e) {
if (marker) {
map.removeLayer(marker);
}
marker = L.marker(e.latlng).addTo(map);
document.querySelector('input[name="latitude"]').value = e.latlng.lat;
document.querySelector('input[name="longitude"]').value = e.latlng.lng;
});
// If editing, set the marker to the existing coordinates
var latInput = document.querySelector('input[name="latitude"]');
var lngInput = document.querySelector('input[name="longitude"]');
if (latInput.value && lngInput.value) {
marker = L.marker([latInput.value, lngInput.value]).addTo(map);
}
</script>
</form>
<a href="/dashboard">Back to Dashboard</a>
</body>
</html>

11
templates/dashboard.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<h2>Welcome, {{ name }}!</h2>
<p>This is the dashboard. More features will be added soon!</p>
<a href="/logout">Logout</a>
</body>
</html>

39
templates/edit_sar.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
var map = L.map('map').setView([51.505, -0.09], 13); // Default to London, adjust as needed
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var marker;
map.on('click', function(e) {
if (marker) {
map.removeLayer(marker);
}
marker = L.marker(e.latlng).addTo(map);
document.querySelector('input[name="latitude"]').value = e.latlng.lat;
document.querySelector('input[name="longitude"]').value = e.latlng.lng;
});
// If editing, set the marker to the existing coordinates
var latInput = document.querySelector('input[name="latitude"]');
var lngInput = document.querySelector('input[name="longitude"]');
if (latInput.value && lngInput.value) {
marker = L.marker([latInput.value, lngInput.value]).addTo(map);
}
</script>
</body>
</html>

37
templates/list_sar.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>List of SAR Calls</title>
</head>
<body>
<h2>List of SAR Calls</h2>
<table>
<thead>
<tr>
<th>Start Date</th>
<th>Finish Date</th>
<th>Category</th>
<th>Latitude</th>
<th>Longitude</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for sar in sar_calls %}
<tr>
<td>{{ sar.start_date }}</td>
<td>{{ sar.finish_date }}</td>
<td>{{ sar.category }}</td>
<td>{{ sar.latitude }}</td>
<td>{{ sar.longitude }}</td>
<td>
<a href="{{ url_for('edit_sar', id=sar.id) }}">Edit</a> |
<a href="{{ url_for('delete_sar', id=sar.id) }}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="/dashboard">Back to Dashboard</a>
</body>
</html>

25
templates/login.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form action="/login" method="post">
<div>
<label for="username">Username:</label>
<input type="text" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" required>
</div>
<div>
<input type="submit" value="Login">
</div>
</form>
<div>
Don't have an account? <a href="/register">Register</a>
</div>
</body>
</html>

37
templates/register.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
</head>
<body>
<h2>Register</h2>
<form action="/register" method="post">
<div>
<label for="username">Username:</label>
<input type="text" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" name="email" required>
</div>
<div>
<label for="full_name">Full Name:</label>
<input type="text" name="full_name" required>
</div>
<div>
<label for="phone_number">Phone Number:</label>
<input type="tel" name="phone_number">
</div>
<div>
<input type="submit" value="Register">
</div>
</form>
<div>
Already have an account? <a href="/login">Login</a>
</div>
</body>
</html>