Added display of records without login

This commit is contained in:
Vadim Likholetov 2023-11-19 23:08:19 +02:00
parent 2143b261ac
commit 81858e309d
9 changed files with 107 additions and 47 deletions

12
.idea/dataSources.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="mysql@localhost" uuid="5dc17320-52b3-48ce-b415-835ec0d6e7b6">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/sarbaseapp</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{leaflet-control-geocoder}" />
</component>
</project>

View File

@ -23,10 +23,10 @@ class UserModelView(AdminModelView):
admin = Admin(app, name='SAR Admin', template_mode='bootstrap3')
admin.add_view(UserModelView(User, db.session))
admin.add_view(AdminModelView(Role, db.session))
admin.add_view(AdminModelView(SARCall, db.session))
admin.add_view(AdminModelView(Comment, db.session))
admin.add_view(AdminModelView(GPSTrack, db.session))
admin.add_view(AdminModelView(Role, db.session, category="Dictionaries"))
admin.add_view(AdminModelView(SARCategory, db.session, category="Dictionaries"))
admin.add_view(AdminModelView(SARStatus, db.session, category="Dictionaries"))
admin.add_view(AdminModelView(SARResult, db.session, category="Dictionaries"))

2
app.py
View File

@ -47,7 +47,7 @@ import dashboard
@app.route('/')
def hello_world(): # put application's code here
return redirect(url_for('dashboard'))
return redirect(url_for('list_sar'))
@app.route('/set_language/<lang_code>')

View File

@ -30,6 +30,7 @@ class SARCall(db.Model):
def __repr__(self):
return self.title
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
created = db.Column(db.DateTime, nullable=False, default=datetime.now)

View File

@ -1,10 +1,11 @@
from dateutil import parser
from flask import request, redirect, flash, render_template, url_for, jsonify, Response
from flask_login import login_required, current_user
from sqlalchemy import or_
from sqlalchemy import or_, and_
from sqlalchemy.orm import aliased
from app import app, db
from models import SARCall, Comment, GPSTrack, SARCategory, SARStatus, User, Role
from models import SARCall, Comment, GPSTrack, SARCategory, SARStatus, User, Role, SARResult
@app.route('/create_sar', methods=['GET', 'POST'])
@ -14,7 +15,6 @@ def create_sar():
statuses = SARStatus.query.order_by('id').all()
managers = User.query.join(Role).filter(or_(Role.name == 'search manager', Role.name == 'admin')).all()
if request.method == 'POST':
start_date = parser.parse(request.form.get('start_date'))
category = request.form.get('category')
@ -50,12 +50,20 @@ def create_sar():
@app.route('/list_sar')
@login_required
def list_sar():
sar_calls = SARCall.query.join(User, SARCall.search_officer_id == User.id).join(SARCategory,
SARCall.category == SARCategory.id).add_columns(
SARCategory, User, SARCall).all()
return render_template('list_sar.html', sar_calls=sar_calls)
is_logged_in = current_user.is_authenticated
search_officer = aliased(User)
coordination_officer = aliased(User)
sar_calls = (SARCall.query
.outerjoin(search_officer, and_ (SARCall.search_officer_id == search_officer.id, SARCall.search_officer_id != None))
.join(coordination_officer, SARCall.coordination_officer_id == coordination_officer.id)
.join(SARCategory, SARCall.category == SARCategory.id)
.join(SARStatus, SARCall.status == SARStatus.id)
.add_columns(SARCategory, SARCall, SARStatus)
.all())
return render_template('list_sar.html', sar_calls=sar_calls, is_logged_in=is_logged_in)
@app.route('/edit_sar/<int:id>', methods=['GET', 'POST'])
@ -94,12 +102,27 @@ def edit_sar(id):
@app.route('/sar_details/<int:id>')
def sar_details(id):
sar = SARCall.query.get_or_404(id) # Fetch the SARCall record or return 404
is_logged_in = current_user.is_authenticated
search_officer = aliased(User)
coordination_officer = aliased(User)
sar = (SARCall.query
.outerjoin(search_officer,
and_(SARCall.search_officer_id == search_officer.id, SARCall.search_officer_id != None))
.join(coordination_officer, SARCall.coordination_officer_id == coordination_officer.id)
.join(SARCategory, SARCall.category == SARCategory.id)
.join(SARStatus, SARCall.status == SARStatus.id)
.outerjoin(SARResult, and_(SARCall.result == SARResult.id, SARCall.result != None))
.add_columns(SARCall, SARCategory, SARStatus, SARResult)
.filter(SARCall.id == id).first())
comments = Comment.query.filter_by(sar_call_id=id).all()
gpx_files = [id[0] for id in GPSTrack.query.with_entities(GPSTrack.id).filter_by(
sar_call_id=id).all()] # Fetch all GPX files for this SARCall
comments_with_gpx = []
for comment in sar.comments:
for comment in comments:
gpx_tracks = GPSTrack.query.filter_by(comment_id=comment.id).all()
for track in gpx_tracks:
comments_with_gpx.append({
@ -109,7 +132,9 @@ def sar_details(id):
"comment": track.gpx_name
})
return render_template('sar_details.html', sar=sar, gpx_ids=gpx_files, comments_with_gpx=comments_with_gpx)
print(sar)
return render_template('sar_details.html', sar=sar, gpx_ids=gpx_files, comments_with_gpx=comments_with_gpx,is_logged_in=is_logged_in)
@app.route('/delete_sar/<int:id>')
@ -180,7 +205,6 @@ def upload_gpx():
@app.route('/get_gpx/<int:gpx_id>')
@login_required
def get_gpx(gpx_id):
gpx_file = GPSTrack.query.get_or_404(gpx_id)
return Response(gpx_file.gpx_data, mimetype='application/gpx+xml')

View File

@ -21,9 +21,11 @@
<li class="nav-item">
<a class="nav-link" href="/list_sar">{{ _('SAR records') }}</a>
</li>
{% if current_user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="/create_sar">{{ _('New record') }}</a>
</li>
{% endif %}
</ul>
<!-- Display user info and logout link if user is authenticated -->

View File

@ -18,7 +18,10 @@
<th>Category</th>
<th>Created by</th>
<th>Manager</th>
{% if is_logged_in %}
<th>Actions</th>
{% endif %}
</tr>
</thead>
<tbody>
@ -26,25 +29,27 @@
<tr class="clickable-row" data-href="{{ url_for('sar_details', id=sar.SARCall.id) }}">
<td>{{ sar.SARCall.id }}</td>
<td>{{ sar.SARCall.title }}</td>
<td>{{ sar.SARCall.status }}</td>
<td>{{ sar.SARStatus.name }}</td>
<td>{{ sar.SARCall.start_date }}</td>
<td>{{ sar.SARCall.finish_date }}</td>
<td>{{ sar.SARCategory.name }}</td>
<td>{{ sar.User.full_name }}</td>
<td>{{ sar.SARCall.manager }}</td>
<td>{{ sar.SARCall.coordination_officer.full_name }}</td>
<td>{{ sar.SARCall.search_officer.full_name }}</td>
{% if is_logged_in %}
<td>
<a href="{{ url_for('edit_sar', id=sar.SARCall.id) }}">
<button type="button" class="btn btn-info">Edit</button>
</a> |
<a href="{{ url_for('delete_sar', id=sar.SARCall.id) }}">
<button type="button" class="btn btn-danger">Delete</button>
</a>
{# <a href="{{ url_for('delete_sar', id=sar.SARCall.id) }}">#}
{# <button type="button" class="btn btn-danger">Delete</button>#}
{# </a>#}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<a href="/dashboard">Back to Dashboard</a>
{# <a href="/dashboard">Back to Dashboard</a>#}
</div>
<script>

View File

@ -28,7 +28,7 @@
</style>
<div class="container mt-4">
<h2 class="mb-4">#{{ sar.id }} : {{ sar.title }}</h2>
<h2 class="mb-4">#{{ sar.SARCall.id }} : {{ sar.SARCall.title }}</h2>
<div class="card mb-4">
<div class="card-body">
<table>
@ -37,27 +37,32 @@
<div class="card-mb5">
<div class="card-body">
<div>
<p>Created at: {{ sar.created }}</p>
<p>Last updated: {{ sar.updated }}</p>
<p>Created at: {{ sar.SARCall.created }}</p>
<p>Last updated: {{ sar.SARCall.updated }}</p>
</div>
<p>Status: {{ sar.status }}</p>
<p>Category: {{ sar.category }}</p>
<p><strong>Start Date:</strong> {{ sar.start_date }}</p>
<p><strong>Finish Date:</strong> {{ sar.finish_date }}</p>
<p>Result: {{ sar.result }}</p>
<p><strong>Manager:</strong> {{ sar.manager_id }}</p>
<p><strong>Coordination manager:</strong> {{ sar.SARCall.coordination_officer.full_name }}</p>
<p><strong>Search manager:</strong> {{ sar.SARCall.search_officer.full_name }}</p>
<p>Status: {{ sar.SARStatus.name }}</p>
{% if is_logged_in %}
<p>Category: {{ sar.SARCategory.name }}</p>
{% endif %}
<p><strong>Start Date:</strong> {{ sar.SARCall.start_date }}</p>
<p><strong>Finish Date:</strong> {{ sar.SARCall.finish_date }}</p>
<p>Result: {{ sar.SARResult.name }}</p>
</div>
</div>
</td>
<td>
<div class="card-mb5">
<div class="card-body">
<p>IPP longitude: {{ sar.longitude }} </p>
<p>IPP latitude: {{ sar.latitude }}</p>
<p>Longitude found: {{ sar.longitude_found }}</p>
<p>Latitude found: {{ sar.latitude_found }}</p>
<p>Description: {{ sar.description }}</p>
<p>Description private: {{ sar.description_hidden }}</p>
<p>IPP longitude: {{ sar.SARCall.longitude }} </p>
<p>IPP latitude: {{ sar.SARCall.latitude }}</p>
<p>Longitude found: {{ sar.SARCall.longitude_found }}</p>
<p>Latitude found: {{ sar.SARCall.latitude_found }}</p>
<p>Description: {{ sar.SARCall.description }}</p>
{% if is_logged_in %}
<p>Description private: {{ sar.SARCall.description_hidden }}</p>
{% endif %}
</div>
</div>
</td>
@ -68,15 +73,17 @@
</div>
<div>
<a href="{{ url_for('edit_sar', id=sar.id) }}" class="btn btn-primary">Edit</a>
<a href="{{ url_for('delete_sar', id=sar.id) }}" class="btn btn-danger">Delete</a>
{% if is_logged_in %}
<a href="{{ url_for('edit_sar', id=sar.SARCall.id) }}" class="btn btn-primary">Edit</a>
<a href="{{ url_for('delete_sar', id=sar.SARCall.id) }}" class="btn btn-danger">Delete</a>
{% endif %}
</div>
<div id="map" class="mb-4"></div>
<!-- Display Comments -->
{% for comment in sar.comments %}
{% for comment in sar.SARCall.comments %}
<div class="comment">
<div class="card mb-4">
<div class="card-body">
@ -97,7 +104,8 @@
{% endfor %}
{% if current_user.id == comment.user_id or current_user.id == 1 or current_user.id == sar.user_id %}
{% if is_logged_in %}
{% if current_user.id == comment.user_id or current_user.id == 1 or current_user.id == sar.SARCall.user_id %}
<button class="edit-comment-btn" data-comment-id="{{ comment.id }}"
data-comment-text="{{ comment.text }}">Edit
</button>
@ -113,6 +121,7 @@
</button>
{% endif %}
{% endif %}
</div>
</div>
</div>
@ -147,7 +156,8 @@
<!-- Add Comment Form -->
<form action="{{ url_for('add_comment', sar_call_id=sar.id) }}" method="post" enctype="multipart/form-data">
{% if is_logged_in %}
<form action="{{ url_for('add_comment', sar_call_id=sar.SARCall.id) }}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="text">Comment:</label>
<textarea name="text" class="form-control"></textarea>
@ -158,7 +168,7 @@
</div>
<button type="submit" class="btn btn-primary">Add Comment</button>
</form>
{% endif %}
</div>
<!-- GPX File Upload Modal -->
@ -183,7 +193,7 @@
</div>
</div>
<input type="hidden" id="commentIdForGPX" name="commentId">
<input type="hidden" id="sarIdForGPX" name="sarId" value="{{ sar.id }}">
<input type="hidden" id="sarIdForGPX" name="sarId" value="{{ sar.SARCall.id }}">
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Upload</button>
</div>
@ -209,12 +219,12 @@
var gpxData = {{ gpx_ids | tojson }};
var map = L.map('map').setView([{{ sar.latitude }}, {{ sar.longitude }}], 13);
var map = L.map('map').setView([{{ sar.SARCall.latitude }}, {{ sar.SARCall.longitude }}], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
L.marker([{{ sar.latitude }}, {{ sar.longitude }}]).addTo(map);
L.marker([{{ sar.SARCall.latitude }}, {{ sar.SARCall.longitude }}]).addTo(map);
gpxData.forEach(function (id) {
loadAndDisplayGPX(id);