GPX upload functionality implemented
This commit is contained in:
parent
898c14f126
commit
695603c6a9
12
README.md
12
README.md
@ -3,3 +3,15 @@
|
|||||||
An attempt to create search and rescue database for logging SAR jobs and activities.
|
An attempt to create search and rescue database for logging SAR jobs and activities.
|
||||||
|
|
||||||
(c) 2019-2023 Vadim Likholetov
|
(c) 2019-2023 Vadim Likholetov
|
||||||
|
|
||||||
|
|
||||||
|
# How to prepare MySQL database
|
||||||
|
|
||||||
|
mysql> CREATE DATABASE sarbaseapp;
|
||||||
|
mysql> CREATE USER 'sarbaseuser'@'localhost' IDENTIFIED BY 'password';
|
||||||
|
mysql> GRANT ALL PRIVILEGES ON sarbaseapp.* TO 'sarbaseuser'@'localhost';
|
||||||
|
mysql> SET @@GLOBAL.sql_mode := REPLACE(@@GLOBAL.sql_mode, 'NO_ZERO_DATE', '');
|
||||||
|
mysql> FLUSH PRIVILEGES;
|
||||||
|
mysql> EXIT;
|
||||||
|
|
||||||
|
|
||||||
|
32
models.py
32
models.py
@ -1,28 +1,38 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask_login import UserMixin
|
from flask_login import UserMixin
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
|
|
||||||
class User(UserMixin, db.Model):
|
class User(UserMixin, db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
created = db.Column(db.DateTime, nullable=False, default=datetime.now)
|
||||||
|
updated = db.Column(db.DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
|
||||||
username = db.Column(db.String(150), unique=True, nullable=False)
|
username = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
full_name = db.Column(db.String(300), nullable=False)
|
full_name = db.Column(db.String(301), nullable=False)
|
||||||
email = db.Column(db.String(150), unique=True, nullable=False)
|
email = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
phone_number = db.Column(db.String(50), nullable=True)
|
phone_number = db.Column(db.String(50), nullable=True)
|
||||||
password = db.Column(db.String(50))
|
password = db.Column(db.String(50))
|
||||||
role_id = db.Column(db.Integer, db.ForeignKey('role.id'))
|
role_id = db.Column(db.Integer, db.ForeignKey('role.id'))
|
||||||
role = db.relationship('Role', backref=db.backref('users', lazy='dynamic'))
|
role = db.relationship('Role', backref=db.backref('users', lazy='dynamic'))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
|
|
||||||
class Role(db.Model):
|
class Role(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(80), unique=True)
|
name = db.Column(db.String(80), unique=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name # This is so that when we print the Role class, it will print the name instead of the object memory address
|
return self.name # This is so that when we print the Role class, it will print the name instead of the object memory address
|
||||||
|
|
||||||
|
|
||||||
class SARCall(db.Model):
|
class SARCall(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
created = db.Column(db.DateTime, nullable=False, default=datetime.now)
|
||||||
|
updated = db.Column(db.DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
|
||||||
start_date = db.Column(db.DateTime, nullable=False)
|
start_date = db.Column(db.DateTime, nullable=False)
|
||||||
finish_date = db.Column(db.DateTime, nullable=True)
|
finish_date = db.Column(db.DateTime, nullable=True)
|
||||||
category = db.Column(db.Integer, db.ForeignKey('sar_category.id'), nullable=False)
|
category = db.Column(db.Integer, db.ForeignKey('sar_category.id'), nullable=False)
|
||||||
@ -30,41 +40,55 @@ class SARCall(db.Model):
|
|||||||
result = db.Column(db.Integer, db.ForeignKey('sar_result.id'), nullable=True)
|
result = db.Column(db.Integer, db.ForeignKey('sar_result.id'), nullable=True)
|
||||||
latitude = db.Column(db.Float, nullable=False)
|
latitude = db.Column(db.Float, nullable=False)
|
||||||
longitude = db.Column(db.Float, nullable=False)
|
longitude = db.Column(db.Float, nullable=False)
|
||||||
|
latitude_found = db.Column(db.Float, nullable=True)
|
||||||
|
longitude_found = db.Column(db.Float, nullable=True)
|
||||||
title = db.Column(db.String(150), nullable=False)
|
title = db.Column(db.String(150), nullable=False)
|
||||||
description = db.Column(db.Text, nullable=True)
|
description = db.Column(db.Text, nullable=True)
|
||||||
description_hidden = db.Column(db.Text, nullable=True)
|
description_hidden = db.Column(db.Text, nullable=True)
|
||||||
search_manager_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
search_manager_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||||
search_manager = db.relationship('User', backref=db.backref('sar_calls', lazy=True))
|
search_manager = db.relationship('User', backref=db.backref('sar_calls', lazy=True))
|
||||||
|
|
||||||
|
|
||||||
class SARCategory(db.Model):
|
class SARCategory(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
||||||
name = db.Column(db.String(150), unique=True, nullable=False)
|
name = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name # Assuming 'name' is the field you want to display
|
return self.name # Assuming 'name' is the field you want to display
|
||||||
|
|
||||||
|
|
||||||
class SARResult(db.Model):
|
class SARResult(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
||||||
name = db.Column(db.String(150), unique=True, nullable=False)
|
name = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name # Assuming 'name' is the field you want to display
|
return self.name # Assuming 'name' is the field you want to display
|
||||||
|
|
||||||
|
|
||||||
class SARStatus(db.Model):
|
class SARStatus(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
|
||||||
name = db.Column(db.String(150), unique=True, nullable=False)
|
name = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name # Assuming 'name' is the field you want to display
|
return self.name # Assuming 'name' is the field you want to display
|
||||||
|
|
||||||
|
|
||||||
class GPSTrack(db.Model):
|
class GPSTrack(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
data = db.Column(db.Text, nullable=False)
|
file_name = db.Column(db.String(255), nullable=False)
|
||||||
|
gpx_name = db.Column(db.Text, nullable=True)
|
||||||
|
gpx_data = db.Column(db.Text(length=4294967295), nullable=True)
|
||||||
color = db.Column(db.String(7)) # Stores the color as a HEX code like #FF5733
|
color = db.Column(db.String(7)) # Stores the color as a HEX code like #FF5733
|
||||||
|
comment_id = db.Column(db.Integer, db.ForeignKey('comment.id'), nullable=False)
|
||||||
|
comment = db.relationship('Comment', backref=db.backref('gps_track', lazy=True))
|
||||||
sar_call_id = db.Column(db.Integer, db.ForeignKey('sar_call.id'), nullable=False)
|
sar_call_id = db.Column(db.Integer, db.ForeignKey('sar_call.id'), nullable=False)
|
||||||
sar_call = db.relationship('SARCall', backref=db.backref('gps_tracks', lazy=True))
|
|
||||||
|
|
||||||
class Comment(db.Model):
|
class Comment(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
created = db.Column(db.DateTime, nullable=False, default=datetime.now)
|
||||||
|
updated = db.Column(db.DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
|
||||||
text = db.Column(db.Text, nullable=True)
|
text = db.Column(db.Text, nullable=True)
|
||||||
gpx_data = db.Column(db.Text (length=4294967295) , nullable=True)
|
|
||||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||||
user = db.relationship('User', backref=db.backref('comments', lazy=True))
|
user = db.relationship('User', backref=db.backref('comments', lazy=True))
|
||||||
sar_call_id = db.Column(db.Integer, db.ForeignKey('sar_call.id'), nullable=False)
|
sar_call_id = db.Column(db.Integer, db.ForeignKey('sar_call.id'), nullable=False)
|
||||||
|
41
sar_calls.py
41
sar_calls.py
@ -1,8 +1,9 @@
|
|||||||
from app import app, db
|
from dateutil import parser
|
||||||
from flask import request, redirect, flash, render_template, url_for, jsonify
|
from flask import request, redirect, flash, render_template, url_for, jsonify
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from dateutil import parser
|
|
||||||
from models import SARCall, Comment, GPSTrack, SARCategory, SARStatus, User
|
from app import app, db
|
||||||
|
from models import SARCall, Comment, GPSTrack, SARCategory, SARStatus, User
|
||||||
|
|
||||||
|
|
||||||
@app.route('/create_sar', methods=['GET', 'POST'])
|
@app.route('/create_sar', methods=['GET', 'POST'])
|
||||||
@ -49,7 +50,9 @@ def create_sar():
|
|||||||
@app.route('/list_sar')
|
@app.route('/list_sar')
|
||||||
@login_required
|
@login_required
|
||||||
def list_sar():
|
def list_sar():
|
||||||
sar_calls = SARCall.query.join(User, SARCall.search_manager_id == User.id).join(SARCategory, SARCall.category == SARCategory.id).add_columns(SARCategory, User, SARCall).all()
|
sar_calls = SARCall.query.join(User, SARCall.search_manager_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)
|
return render_template('list_sar.html', sar_calls=sar_calls)
|
||||||
|
|
||||||
|
|
||||||
@ -74,7 +77,6 @@ def edit_sar(id):
|
|||||||
sar_call.description_hidden = request.form.get('description_hidden')
|
sar_call.description_hidden = request.form.get('description_hidden')
|
||||||
# sar_call.gpx_data = request.form.get('gpx_data')
|
# sar_call.gpx_data = request.form.get('gpx_data')
|
||||||
|
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('SAR call updated successfully!', 'success')
|
flash('SAR call updated successfully!', 'success')
|
||||||
return redirect(url_for('list_sar'))
|
return redirect(url_for('list_sar'))
|
||||||
@ -84,15 +86,14 @@ def edit_sar(id):
|
|||||||
if sar_call.finish_date:
|
if sar_call.finish_date:
|
||||||
sar_call.finish_date = sar_call.finish_date.strftime('%Y-%m-%d')
|
sar_call.finish_date = sar_call.finish_date.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
return render_template('edit_sar.html', sar_call=sar_call,categories=categories, statuses=statuses)
|
return render_template('edit_sar.html', sar_call=sar_call, categories=categories, statuses=statuses)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/sar_details/<int:id>')
|
@app.route('/sar_details/<int:id>')
|
||||||
def sar_details(id):
|
def sar_details(id):
|
||||||
sar = SARCall.query.get_or_404(id) # Fetch the SARCall record or return 404
|
sar = SARCall.query.get_or_404(id) # Fetch the SARCall record or return 404
|
||||||
return render_template('sar_details.html', sar=sar)
|
gpx_files = GPSTrack.query.filter_by(sar_call_id=id).all()
|
||||||
|
return render_template('sar_details.html', sar=sar, gpx_files=gpx_files)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delete_sar/<int:id>')
|
@app.route('/delete_sar/<int:id>')
|
||||||
@ -130,6 +131,7 @@ def edit_comment(comment_id):
|
|||||||
# return jsonify(success=True) # or return relevant response
|
# return jsonify(success=True) # or return relevant response
|
||||||
return redirect(url_for('sar_details', id=comment.sar_call_id))
|
return redirect(url_for('sar_details', id=comment.sar_call_id))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delete_comment/<int:id>', methods=['GET', 'POST'])
|
@app.route('/delete_comment/<int:id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_comment(id):
|
def delete_comment(id):
|
||||||
@ -140,3 +142,24 @@ def delete_comment(id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('Comment deleted successfully!', 'success')
|
flash('Comment deleted successfully!', 'success')
|
||||||
return redirect(url_for('sar_details', id=comment.sar_call_id))
|
return redirect(url_for('sar_details', id=comment.sar_call_id))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/upload_gpx', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def upload_gpx():
|
||||||
|
# Retrieve file and other data from the form
|
||||||
|
file_name = request.form.get('gpxFileName')
|
||||||
|
gpx_file = request.files.get('gpxFile')
|
||||||
|
id = request.form.get('commentId')
|
||||||
|
sar_id = request.form.get('sarId')
|
||||||
|
|
||||||
|
# You need to implement logic to parse and store the GPX file
|
||||||
|
# For example, read the file content
|
||||||
|
gpx_data = gpx_file.read()
|
||||||
|
|
||||||
|
# Create a new GPSTrack object and save it
|
||||||
|
new_gpx_file = GPSTrack(comment_id=id, sar_call_id=sar_id, file_name=file_name, gpx_data=gpx_data)
|
||||||
|
db.session.add(new_gpx_file)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify({'message': 'GPX file uploaded successfully'})
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/>
|
<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>
|
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Include leaflet-gpx plugin -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.5.1/gpx.min.js"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#map {
|
#map {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
@ -17,6 +21,10 @@
|
|||||||
.button {
|
.button {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment-text {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
@ -24,6 +32,10 @@
|
|||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p><strong>ID:</strong> {{ sar.id }}</p>
|
<p><strong>ID:</strong> {{ sar.id }}</p>
|
||||||
|
<div>
|
||||||
|
<p>Created at: {{ sar.created }}</p>
|
||||||
|
<p>Last updated: {{ sar.updated }}</p>
|
||||||
|
</div>
|
||||||
<p><strong>Start Date:</strong> {{ sar.start_date }}</p>
|
<p><strong>Start Date:</strong> {{ sar.start_date }}</p>
|
||||||
<p><strong>Manager:</strong> {{ sar.manager }}</p>
|
<p><strong>Manager:</strong> {{ sar.manager }}</p>
|
||||||
<!-- Other SAR details -->
|
<!-- Other SAR details -->
|
||||||
@ -42,7 +54,11 @@
|
|||||||
{% for comment in sar.comments %}
|
{% for comment in sar.comments %}
|
||||||
<div class="comment">
|
<div class="comment">
|
||||||
<strong>{{ comment.user.username }}</strong>:
|
<strong>{{ comment.user.username }}</strong>:
|
||||||
<p id="comment-text-{{ comment.id }}">{{ comment.text }}</p>
|
<div>
|
||||||
|
<p>Comment created at: {{ comment.created }}</p>
|
||||||
|
<p>Last updated: {{ comment.updated }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="comment-text"><p id="comment-text-{{ comment.id }}">{{ comment.text }}</p></div>
|
||||||
|
|
||||||
{% if comment.gpx_data %}
|
{% if comment.gpx_data %}
|
||||||
<!-- Display the GPX data on the map -->
|
<!-- Display the GPX data on the map -->
|
||||||
@ -51,8 +67,13 @@
|
|||||||
<button class="edit-comment-btn" data-comment-id="{{ comment.id }}"
|
<button class="edit-comment-btn" data-comment-id="{{ comment.id }}"
|
||||||
data-comment-text="{{ comment.text }}">Edit
|
data-comment-text="{{ comment.text }}">Edit
|
||||||
</button>
|
</button>
|
||||||
|
<!-- Button to Open GPX Upload Modal -->
|
||||||
|
<button type="button" class="gpx-upload-button" data-toggle="modal" data-target="#uploadGPXModal"
|
||||||
|
data-comment-id="{{ comment.id }}">
|
||||||
|
Upload GPX File
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="delete-comment-btn">
|
<button type="button" class="delete-comment-btn">
|
||||||
<a href="{{ url_for('delete_comment', id=comment.id) }}">Delete</a>
|
<a href="{{ url_for('delete_comment', id=comment.id) }}">Delete</a>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@ -95,21 +116,61 @@
|
|||||||
<textarea name="text" class="form-control"></textarea>
|
<textarea name="text" class="form-control"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="gpx_file">GPX File:</label>
|
|
||||||
<input type="file" name="gpx_file">
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Add Comment</button>
|
<button type="submit" class="btn btn-primary">Add Comment</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- GPX File Upload Modal -->
|
||||||
|
<div class="modal fade" id="uploadGPXModal" tabindex="-1" aria-labelledby="uploadGPXModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="uploadGPXModalLabel">Upload GPX File</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form id="uploadGPXForm" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="gpxFileName">Description: </label>
|
||||||
|
<input type="text" class="form-control" id="gpxFileName" name="gpxFileName" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="gpxFile">GPX File</label>
|
||||||
|
<input type="file" class="form-control" id="gpxFile" name="gpxFile" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="commentIdForGPX" name="commentId">
|
||||||
|
<input type="hidden" id="sarIdForGPX" name="sarId" value="{{ sar.id }}">
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary">Upload</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var gpxData = {{ gpx_files | tojson }};
|
||||||
|
|
||||||
var map = L.map('map').setView([{{ sar.latitude }}, {{ sar.longitude }}], 13);
|
var map = L.map('map').setView([{{ sar.latitude }}, {{ sar.longitude }}], 13);
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
attribution: '© OpenStreetMap contributors'
|
attribution: '© OpenStreetMap contributors'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
L.marker([{{ sar.latitude }}, {{ sar.longitude }}]).addTo(map);
|
L.marker([{{ sar.latitude }}, {{ sar.longitude }}]).addTo(map);
|
||||||
|
|
||||||
|
gpxData.forEach(function (gpxFile) {
|
||||||
|
new L.GPX(gpxFile.gpx_data, {async: true}).on('loaded', function (e) {
|
||||||
|
map.fitBounds(e.target.getBounds());
|
||||||
|
}).addTo(map);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@ -134,7 +195,8 @@
|
|||||||
data: {comment: $('#commentText').val()},
|
data: {comment: $('#commentText').val()},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
// Update the comment display on the page
|
// Update the comment display on the page
|
||||||
$('#comment-text-' + commentId).text( $('#commentText').val());
|
$('#comment-text-' + commentId).text($('#commentText').val());
|
||||||
|
$('button.edit-comment-btn[data-comment-id="' + commentId + '"]').data('comment-text', $('#commentText').val());
|
||||||
$('#editCommentModal').modal('hide');
|
$('#editCommentModal').modal('hide');
|
||||||
// Update the comment display on the page as needed
|
// Update the comment display on the page as needed
|
||||||
},
|
},
|
||||||
@ -149,4 +211,42 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var commentId;
|
||||||
|
|
||||||
|
$('.gpx-upload-button').on('click', function () {
|
||||||
|
var commentId = $(this).data('comment-id');
|
||||||
|
$('#commentIdForGPX').val(commentId);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
{#commentId = $(this).data('comment-id');#}
|
||||||
|
{#console.log(commentId);#}
|
||||||
|
// Handle form submission
|
||||||
|
$('#uploadGPXForm').on('submit', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var formData = new FormData(this);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/upload_gpx', // Update with the correct route
|
||||||
|
type: 'POST',
|
||||||
|
data: formData,
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
success: function (response) {
|
||||||
|
// Handle success - Close modal, Update the map with new GPX data
|
||||||
|
$('#uploadGPXModal').modal('hide');
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
// Handle error
|
||||||
|
alert("Error uploading GPX file");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
Reference in New Issue
Block a user