Compare commits
3 Commits
7018ae13f0
...
73b90eafbc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73b90eafbc | ||
|
|
5a6dbc46eb | ||
|
|
1d12a882c1 |
@@ -273,8 +273,8 @@ def new_post():
|
|||||||
original_name=cover_file.filename,
|
original_name=cover_file.filename,
|
||||||
size=result['size'],
|
size=result['size'],
|
||||||
mime_type=result['mime_type'],
|
mime_type=result['mime_type'],
|
||||||
post_id=post.id
|
post_id=post.id,
|
||||||
# Note: is_cover column missing, will be added in future migration
|
is_cover=True # Mark as cover image
|
||||||
)
|
)
|
||||||
db.session.add(cover_image)
|
db.session.add(cover_image)
|
||||||
current_app.logger.info(f'Cover image saved: {result["filename"]}')
|
current_app.logger.info(f'Cover image saved: {result["filename"]}')
|
||||||
@@ -300,6 +300,32 @@ def new_post():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.warning(f'Error processing GPX file: {str(e)}')
|
current_app.logger.warning(f'Error processing GPX file: {str(e)}')
|
||||||
|
|
||||||
|
# Handle section images (multiple images from content sections)
|
||||||
|
section_images_processed = 0
|
||||||
|
for key in request.files.keys():
|
||||||
|
if key.startswith('section_image_') and not key.endswith('_section'):
|
||||||
|
try:
|
||||||
|
image_file = request.files[key]
|
||||||
|
if image_file and image_file.filename:
|
||||||
|
current_app.logger.info(f'Processing section image: {image_file.filename}')
|
||||||
|
result = save_image(image_file, post.id)
|
||||||
|
if result['success']:
|
||||||
|
section_image = PostImage(
|
||||||
|
filename=result['filename'],
|
||||||
|
original_name=image_file.filename,
|
||||||
|
size=result['size'],
|
||||||
|
mime_type=result['mime_type'],
|
||||||
|
post_id=post.id,
|
||||||
|
is_cover=False # Section images are not cover images
|
||||||
|
)
|
||||||
|
db.session.add(section_image)
|
||||||
|
section_images_processed += 1
|
||||||
|
current_app.logger.info(f'Section image saved: {result["filename"]}')
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.warning(f'Error processing section image {key}: {str(e)}')
|
||||||
|
|
||||||
|
current_app.logger.info(f'Total section images processed: {section_images_processed}')
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
current_app.logger.info(f'Post {post.id} committed to database successfully')
|
current_app.logger.info(f'Post {post.id} committed to database successfully')
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,14 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden md:flex items-center space-x-8">
|
<div class="hidden md:flex items-center space-x-8">
|
||||||
<a href="{{ url_for('main.index') }}" class="text-white hover:text-blue-200 transition">Landing</a>
|
|
||||||
<a href="{{ url_for('community.index') }}" class="text-white hover:text-teal-200 transition font-semibold">🏍️ Adventures</a>
|
<a href="{{ url_for('community.index') }}" class="text-white hover:text-teal-200 transition font-semibold">🏍️ Adventures</a>
|
||||||
<a href="{{ url_for('main.index') }}#accommodation" class="text-white hover:text-purple-200 transition">Accommodation</a>
|
<a href="{{ url_for('main.index') }}#accommodation" class="text-white hover:text-purple-200 transition">Accommodation</a>
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<a href="{{ url_for('community.new_post') }}" class="bg-gradient-to-r from-green-500 to-emerald-500 text-white px-4 py-2 rounded-lg hover:from-green-400 hover:to-emerald-400 transition transform hover:scale-105">
|
{% if not current_user.is_admin %}
|
||||||
<i class="fas fa-plus mr-2"></i>Share Adventure
|
<a href="{{ url_for('community.new_post') }}" class="bg-gradient-to-r from-green-500 to-emerald-500 text-white px-4 py-2 rounded-lg hover:from-green-400 hover:to-emerald-400 transition transform hover:scale-105">
|
||||||
</a>
|
<i class="fas fa-plus mr-2"></i>Share Adventure
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
<a href="{{ url_for('community.profile') }}" class="text-white hover:text-blue-200 transition">
|
<a href="{{ url_for('community.profile') }}" class="text-white hover:text-blue-200 transition">
|
||||||
<i class="fas fa-user mr-1"></i>My Profile
|
<i class="fas fa-user mr-1"></i>My Profile
|
||||||
</a>
|
</a>
|
||||||
@@ -61,9 +62,11 @@
|
|||||||
<a href="{{ url_for('main.index') }}#accommodation" class="text-white block px-3 py-2 hover:bg-purple-600 rounded">Accommodation</a>
|
<a href="{{ url_for('main.index') }}#accommodation" class="text-white block px-3 py-2 hover:bg-purple-600 rounded">Accommodation</a>
|
||||||
<a href="{{ url_for('community.index') }}" class="text-white block px-3 py-2 hover:bg-teal-600 rounded">Stories & Tracks</a>
|
<a href="{{ url_for('community.index') }}" class="text-white block px-3 py-2 hover:bg-teal-600 rounded">Stories & Tracks</a>
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<a href="{{ url_for('community.new_post') }}" class="text-white block px-3 py-2 hover:bg-green-600 rounded">
|
{% if not current_user.is_admin %}
|
||||||
<i class="fas fa-plus mr-2"></i>New Post
|
<a href="{{ url_for('community.new_post') }}" class="text-white block px-3 py-2 hover:bg-green-600 rounded">
|
||||||
</a>
|
<i class="fas fa-plus mr-2"></i>New Post
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
<a href="{{ url_for('community.profile') }}" class="text-white block px-3 py-2 hover:bg-blue-600 rounded">
|
<a href="{{ url_for('community.profile') }}" class="text-white block px-3 py-2 hover:bg-blue-600 rounded">
|
||||||
<i class="fas fa-user mr-1"></i>My Profile
|
<i class="fas fa-user mr-1"></i>My Profile
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -244,6 +244,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Global storage for section files
|
||||||
|
window.sectionFiles = {};
|
||||||
let sectionCounter = 0;
|
let sectionCounter = 0;
|
||||||
|
|
||||||
// Populate form from URL parameters
|
// Populate form from URL parameters
|
||||||
@@ -418,18 +420,40 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
imageInput.addEventListener('change', function() {
|
imageInput.addEventListener('change', function() {
|
||||||
const files = Array.from(this.files);
|
const files = Array.from(this.files);
|
||||||
|
|
||||||
|
// Store files in global storage for this section
|
||||||
|
if (!window.sectionFiles[sectionId]) {
|
||||||
|
window.sectionFiles[sectionId] = [];
|
||||||
|
}
|
||||||
|
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
if (file.type.startsWith('image/')) {
|
if (file.type.startsWith('image/')) {
|
||||||
|
// Add to global storage
|
||||||
|
window.sectionFiles[sectionId].push(file);
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = function(e) {
|
reader.onload = function(e) {
|
||||||
const imagePreview = document.createElement('div');
|
const imagePreview = document.createElement('div');
|
||||||
imagePreview.className = 'image-preview';
|
imagePreview.className = 'image-preview';
|
||||||
|
imagePreview.dataset.fileIndex = window.sectionFiles[sectionId].length - 1;
|
||||||
imagePreview.innerHTML = `
|
imagePreview.innerHTML = `
|
||||||
<img src="${e.target.result}" alt="Preview">
|
<img src="${e.target.result}" alt="Preview">
|
||||||
<div class="remove-btn">×</div>
|
<div class="remove-btn">×</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
imagePreview.querySelector('.remove-btn').addEventListener('click', function() {
|
imagePreview.querySelector('.remove-btn').addEventListener('click', function() {
|
||||||
|
// Remove from global storage
|
||||||
|
const fileIndex = parseInt(imagePreview.dataset.fileIndex);
|
||||||
|
window.sectionFiles[sectionId].splice(fileIndex, 1);
|
||||||
|
|
||||||
|
// Update indices for remaining previews
|
||||||
|
const remainingPreviews = imagesPreview.querySelectorAll('.image-preview');
|
||||||
|
remainingPreviews.forEach((preview, index) => {
|
||||||
|
if (parseInt(preview.dataset.fileIndex) > fileIndex) {
|
||||||
|
preview.dataset.fileIndex = parseInt(preview.dataset.fileIndex) - 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
imagePreview.remove();
|
imagePreview.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -609,6 +633,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
if (gpxFile) {
|
if (gpxFile) {
|
||||||
formData.append('gpx_file', gpxFile);
|
formData.append('gpx_file', gpxFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add section images from all saved sections
|
||||||
|
let imageCounter = 0;
|
||||||
|
savedSections.forEach((section, sectionIndex) => {
|
||||||
|
const sectionId = section.dataset.sectionId;
|
||||||
|
if (window.sectionFiles[sectionId] && window.sectionFiles[sectionId].length > 0) {
|
||||||
|
window.sectionFiles[sectionId].forEach((file, fileIndex) => {
|
||||||
|
formData.append(`section_image_${imageCounter}`, file);
|
||||||
|
formData.append(`section_image_${imageCounter}_section`, sectionIndex);
|
||||||
|
imageCounter++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Show loading state
|
// Show loading state
|
||||||
const submitBtn = document.querySelector('button[type="submit"]');
|
const submitBtn = document.querySelector('button[type="submit"]');
|
||||||
|
|||||||
Reference in New Issue
Block a user