2024-09-20 17:13:37 +02:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
|
|
|
{% block title %}Post Detail{% endblock %}
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
<div class="container">
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="d-flex align-items-center mb-2">
|
|
|
|
{% if post.author %}
|
|
|
|
{% if post.author.profile_picture %}
|
|
|
|
<img src="{{ url_for('static', filename='uploads/' + post.author.profile_picture) }}" class="rounded-circle me-2" alt="Profile Picture" style="width: 30px; height: 30px; object-fit: cover;">
|
|
|
|
{% else %}
|
|
|
|
<div class="rounded-circle me-2 d-flex justify-content-center align-items-center bg-primary" style="width: 30px; height: 30px;">
|
|
|
|
<span class="text-white" style="font-size: 0.8rem;">{{ post.author.username[0].upper() }}</span>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
<small class="text-muted">
|
|
|
|
<a href="{{ url_for('profile', username=post.author.username) }}" class="text-decoration-none">{{ post.author.username }}</a>
|
|
|
|
</small>
|
|
|
|
{% else %}
|
|
|
|
<small class="text-muted">{{ post.anonymous_username }}</small>
|
|
|
|
{% endif %}
|
|
|
|
<span class="ms-auto text-muted">{{ post.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</span>
|
|
|
|
</div>
|
|
|
|
<p class="card-text">{{ post.content|safe }}</p>
|
|
|
|
{% if post.image_url %}
|
2024-09-24 00:00:18 +02:00
|
|
|
<img src="{{ url_for('static', filename='uploads/' + post.image_url) }}" class="img-fluid mb-2 post-image" alt="Post image" data-bs-toggle="modal" data-bs-target="#imageModal" data-image-url="{{ url_for('static', filename='uploads/' + post.image_url) }}">
|
2024-09-20 17:13:37 +02:00
|
|
|
{% endif %}
|
|
|
|
<div class="d-flex flex-wrap justify-content-between align-items-center">
|
|
|
|
<div class="btn-group mb-2">
|
|
|
|
<button class="btn btn-outline-primary btn-sm like-btn" data-post-id="{{ post.id }}">
|
|
|
|
<i class="bi bi-heart-fill"></i> Like (<span class="like-count">{{ post.likes|length }}</span>)
|
|
|
|
</button>
|
|
|
|
<button class="btn btn-outline-secondary btn-sm comment-btn" data-post-id="{{ post.id }}">
|
|
|
|
<i class="bi bi-chat-fill"></i> Comment ({{ post.comments|length }})
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div class="btn-group mb-2">
|
|
|
|
<button class="btn btn-outline-info btn-sm copy-link-btn" data-post-url="{{ url_for('post_detail', post_id=post.id, _external=True, _scheme='https') }}">
|
|
|
|
<i class="bi bi-link-45deg"></i> Copy Link
|
|
|
|
</button>
|
|
|
|
{% if current_user.is_authenticated and current_user.id == post.author.id %}
|
|
|
|
<a href="{{ url_for('edit_post', post_id=post.id) }}" class="btn btn-outline-warning btn-sm">
|
|
|
|
<i class="bi bi-pencil-fill"></i> Edit
|
|
|
|
</a>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card mt-4">
|
|
|
|
<div class="card-body">
|
|
|
|
<h5 class="card-title mb-3">Comments</h5>
|
|
|
|
<ul class="list-unstyled">
|
|
|
|
{% for comment in post.comments %}
|
|
|
|
{% include 'comment.html' %}
|
|
|
|
{% endfor %}
|
|
|
|
</ul>
|
|
|
|
<form class="comment-form mt-3" data-post-id="{{ post.id }}">
|
|
|
|
<div class="input-group">
|
|
|
|
<input type="text" class="form-control" placeholder="Add a comment" name="content" required>
|
|
|
|
<button class="btn btn-outline-secondary" type="submit">Send</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
|
2024-09-24 00:00:18 +02:00
|
|
|
{% block modals %}
|
|
|
|
<div class="modal fade" id="imageModal" tabindex="-1" aria-labelledby="imageModalLabel" aria-hidden="true">
|
|
|
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
|
|
<div class="modal-content">
|
|
|
|
<div class="modal-header">
|
|
|
|
<h5 class="modal-title" id="imageModalLabel">Image</h5>
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
|
|
</div>
|
|
|
|
<div class="modal-body text-center">
|
|
|
|
<img id="modalImage" src="" class="img-fluid" alt="Post image">
|
|
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
|
|
<button type="button" class="btn btn-primary" id="zoomInButton">Zoom In</button>
|
|
|
|
<button type="button" class="btn btn-primary" id="zoomOutButton">Zoom Out</button>
|
|
|
|
<a id="downloadButton" href="" download class="btn btn-primary">Download</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
|
2024-09-20 17:13:37 +02:00
|
|
|
{% block scripts %}
|
|
|
|
{{ super() }}
|
|
|
|
<script>
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
|
function initializePostInteractions() {
|
|
|
|
// Initialize like button
|
|
|
|
document.querySelector('.like-btn').addEventListener('click', handleLike);
|
|
|
|
|
|
|
|
// Initialize comment button
|
|
|
|
document.querySelector('.comment-btn').addEventListener('click', handleComment);
|
|
|
|
|
|
|
|
// Initialize copy link button
|
|
|
|
document.querySelector('.copy-link-btn').addEventListener('click', handleCopyLink);
|
|
|
|
|
|
|
|
// Initialize comment form
|
|
|
|
document.querySelector('.comment-form').addEventListener('submit', handleCommentSubmit);
|
|
|
|
|
|
|
|
// Initialize comment like buttons
|
|
|
|
document.querySelectorAll('.like-comment-btn').forEach(button => {
|
|
|
|
button.addEventListener('click', handleCommentLike);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleLike(event) {
|
|
|
|
var postId = this.dataset.postId;
|
|
|
|
fetch('/like/' + postId, { method: 'POST' })
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
this.querySelector('.like-count').textContent = data.likes;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleComment(event) {
|
|
|
|
var postId = this.dataset.postId;
|
|
|
|
var commentSection = document.querySelector('.card.mt-4');
|
|
|
|
if (commentSection.style.display === 'none' || commentSection.style.display === '') {
|
|
|
|
commentSection.style.display = 'block';
|
|
|
|
} else {
|
|
|
|
commentSection.style.display = 'none';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleCommentLike(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
var commentId = this.dataset.commentId;
|
|
|
|
fetch('/like_comment/' + commentId, { method: 'POST' })
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
this.querySelector('.comment-like-count').textContent = data.likes;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleCommentSubmit(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
var postId = this.dataset.postId;
|
|
|
|
var content = this.querySelector('input[name="content"]').value;
|
|
|
|
fetch('/comment/' + postId, {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
|
|
},
|
|
|
|
body: 'content=' + encodeURIComponent(content)
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
if (data.success) {
|
|
|
|
var commentList = document.querySelector('.card.mt-4 ul');
|
|
|
|
var newComment = document.createElement('li');
|
|
|
|
newComment.innerHTML = '<strong>' + (data.username !== 'Anonymous' ? '<a href="/profile/' + data.username + '">' + data.username + '</a>' : '<span class="text-white">Anonymous</span>') + ':</strong> ' + data.content +
|
|
|
|
'<button class="btn btn-sm btn-outline-primary like-comment-btn" data-comment-id="' + data.comment_id + '">' +
|
|
|
|
'<i class="bi bi-heart-fill"></i> (<span class="comment-like-count">0</span>)</button>';
|
|
|
|
commentList.appendChild(newComment);
|
|
|
|
this.querySelector('input[name="content"]').value = '';
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleCopyLink(event) {
|
|
|
|
var postUrl = this.dataset.postUrl;
|
|
|
|
navigator.clipboard.writeText(postUrl).then(function() {
|
|
|
|
alert('Link copied to clipboard!');
|
|
|
|
}, function(err) {
|
|
|
|
console.error('Could not copy text: ', err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize interactions for the initial page load
|
|
|
|
initializePostInteractions();
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
{% endblock %}
|