techtalk/templates/profile.html

245 lines
11 KiB
HTML
Raw Normal View History

2024-09-20 17:13:50 +02:00
{% extends "base.html" %}
{% block title %}{{ user.username }}'s Profile{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h1 class="card-title">{{ user.username }}'s Profile</h1>
{% if user.profile_picture %}
<img src="{{ url_for('static', filename='uploads/' + user.profile_picture) }}" class="img-fluid rounded-circle mb-3" alt="Profile Picture" style="background-color: transparent;">
{% else %}
<div class="profile-initial rounded-circle mb-3 d-flex justify-content-center align-items-center bg-primary" style="width: 100px; height: 100px;">
<span class="text-white" style="font-size: 3rem;">{{ user.username[0].upper() }}</span>
</div>
{% endif %}
<p class="card-text"><strong>Bio:</strong></p>
<div class="card-text bio-text">{{ user.rendered_bio|safe or "No bio available." }}</div>
<h5 class="card-title">Stats</h5>
<p class="card-text">Posts: {{ post_count }}</p>
<p class="card-text">Total Likes: {{ like_count }}</p>
<p class="card-text">Total Comments: {{ comment_count }}</p>
{% if current_user.is_authenticated and current_user.id == user.id %}
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#editProfileModal">Edit Profile</button>
{% endif %}
</div>
</div>
</div>
<div class="col-md-8">
<h2>Posts</h2>
{% for post in posts %}
<div class="card mb-3">
<div class="card-body">
<p class="card-text">{{ post.content|safe }}</p>
{% if post.image_url %}
<img src="{{ url_for('static', filename='uploads/' + post.image_url) }}" class="img-fluid mb-2" alt="Post image">
{% endif %}
<div class="d-flex align-items-center mt-2">
{% 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>
</div>
<p class="card-text"><small class="text-muted">{{ post.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</small></p>
<button class="btn btn-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-secondary btn-sm comment-btn" data-post-id="{{ post.id }}">
<i class="bi bi-chat-fill"></i> Comment ({{ post.comments|length }})
</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-warning btn-sm">
<i class="bi bi-pencil-fill"></i> Edit
</a>
{% endif %}
</div>
<div class="card-footer comment-section" id="comment-section-{{ post.id }}" style="display: none;">
<h6>Comments:</h6>
<ul class="list-unstyled">
{% for comment in post.comments if not comment.parent %}
{% with depth=1 %}
{% include 'comment.html' %}
{% endwith %}
{% endfor %}
</ul>
<form class="comment-form" data-post-id="{{ post.id }}">
<div class="input-group mb-3">
<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>
{% endfor %}
</div>
</div>
</div>
<!-- Edit Profile Modal -->
{% if current_user.is_authenticated and current_user.id == user.id %}
<div class="modal fade" id="editProfileModal" tabindex="-1" aria-labelledby="editProfileModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editProfileModalLabel">Edit Profile</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="POST" enctype="multipart/form-data" id="profileForm">
<div class="mb-3">
<label for="bio" class="form-label">Bio</label>
<textarea class="form-control" id="bio" name="bio" rows="5">{{ user.bio }}</textarea>
<small class="form-text text-muted">Markdown and HTML color styling are supported.</small>
</div>
<div class="mb-3">
<label for="profile_picture" class="form-label">Profile Picture</label>
<input type="file" class="form-control" id="profile_picture" name="profile_picture" accept="image/*">
</div>
<div id="cropperContainer" style="display: none;">
<img id="cropperImage" src="" alt="Image to crop" style="max-width: 100%;">
</div>
{% if user.profile_picture %}
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="remove_picture" name="remove_picture">
<label class="form-check-label" for="remove_picture">Remove current profile picture</label>
</div>
{% endif %}
<input type="hidden" name="cropped_data" id="croppedData">
<button type="submit" class="btn btn-primary">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.css">
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<script>
$(document).ready(function() {
let cropper;
$('#profile_picture').change(function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(event) {
$('#cropperImage').attr('src', event.target.result);
$('#cropperContainer').show();
if (cropper) {
cropper.destroy();
}
cropper = new Cropper($('#cropperImage')[0], {
aspectRatio: 1,
viewMode: 1,
minCropBoxWidth: 200,
minCropBoxHeight: 200,
});
}
reader.readAsDataURL(file);
}
});
$('#profileForm').submit(function(e) {
e.preventDefault();
if (cropper) {
const croppedCanvas = cropper.getCroppedCanvas({
width: 200,
height: 200
});
$('#croppedData').val(croppedCanvas.toDataURL());
}
this.submit();
});
var easyMDE = new EasyMDE({
element: document.getElementById('bio'),
spellChecker: false,
autofocus: true,
lineWrapping: true,
toolbar: [
"bold", "italic", "heading", "quote", "unordered-list", "ordered-list",
"link", "code", "table", "undo", "redo",
{
name: "custom-color",
action: function(editor){
var cm = editor.codemirror;
var output = '';
var selectedText = cm.getSelection();
var color = prompt("Enter color (e.g., red, #ff0000, rgb(255,0,0)):");
if (color) {
output = '<span style="color: ' + color + ';">' + selectedText + '</span>';
cm.replaceSelection(output);
}
},
className: "fa fa-paint-brush",
title: "Custom Color",
}
],
status: false,
theme: "dark"
});
// Adjust line height in the editor
easyMDE.codemirror.getWrapperElement().style.lineHeight = "1.3";
});
</script>
{% endblock %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
<style>
.bio-text {
white-space: pre-wrap;
word-wrap: break-word;
max-height: 200px;
overflow-y: auto;
line-height: 1.3; /* Reduce line spacing */
}
.bio-text a {
color: #007bff;
text-decoration: underline;
}
.bio-text a:hover {
color: #0056b3;
}
.EasyMDEContainer {
background-color: #333;
}
.EasyMDEContainer .CodeMirror {
color: #fff;
background-color: #333;
}
.editor-toolbar {
background-color: #444;
border-color: #555;
}
.editor-toolbar button {
color: #fff !important;
}
.editor-toolbar button:hover,
.editor-toolbar button.active {
background-color: #555;
}
.CodeMirror-cursor {
border-left: 1px solid #fff;
}
.CodeMirror-line {
padding: 0 !important; /* Remove extra padding */
}
</style>
{% endblock %}