163 lines
6.4 KiB
HTML
163 lines
6.4 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
{% load markdown %}
|
|
|
|
{% block title %}{{ profile_user.username }} - Packs{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="profile-header card">
|
|
<div class="profile-avatar">
|
|
{% if profile.avatar %}
|
|
<img src="{{ profile.avatar_url }}" alt="{{ profile_user.username }} avatar">
|
|
{% else %}
|
|
<div class="default-avatar large">{{ profile_user.username|first|upper }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="profile-info">
|
|
<h1>{{ profile_user.username }}
|
|
{% if profile_user.is_superuser %}
|
|
<span class="badge badge-admin" title="Administrator"><i class="fas fa-crown"></i> Admin</span>
|
|
{% elif profile_user.is_staff %}
|
|
<span class="badge badge-staff" title="Staff"><i class="fas fa-user-shield"></i> Staff</span>
|
|
{% endif %}
|
|
</h1>
|
|
<p class="profile-joined"><i class="fas fa-calendar"></i> Joined {{ profile.joined|date:"F j, Y" }}</p>
|
|
{% if can_impersonate %}
|
|
<form method="post" action="{% url 'profiles:impersonate_start' profile_user.pk %}" class="impersonate-form">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-secondary" id="impersonate-btn">
|
|
<i class="fas fa-mask"></i> Impersonate
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if is_owner %}
|
|
<p><a href="{% url 'profiles:account' %}" class="btn btn-secondary"><i class="fas fa-cog"></i> Account Settings</a></p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<section class="card profile-section">
|
|
<h2><i class="fas fa-comment"></i> Bio</h2>
|
|
{% if is_owner %}
|
|
{% if messages %}
|
|
<ul class="messages">
|
|
{% for message in messages %}
|
|
<li>{{ message }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
<form method="post" action="{% url 'profiles:user_profile' profile_user.username %}">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="action" value="bio">
|
|
<div class="form-group">
|
|
{{ bio_form.bio.errors }}
|
|
{{ bio_form.bio }}
|
|
</div>
|
|
<p class="bio-help"><i class="fas fa-info-circle"></i> Supports <a href="#" data-md-help>Markdown</a> — headings, lists, links, code, tables and more.</p>
|
|
<div class="bio-actions">
|
|
<button type="submit" class="btn btn-primary">Save bio</button>
|
|
<button type="button" class="btn btn-secondary" data-bio-toggle>Preview</button>
|
|
</div>
|
|
</form>
|
|
<div class="markdown-preview markdown-body" id="bio-preview" hidden></div>
|
|
{% else %}
|
|
{% if profile.bio %}
|
|
<div class="profile-bio markdown-body">{{ profile.bio|markdown }}</div>
|
|
{% else %}
|
|
<p class="profile-bio-empty"><i class="fas fa-user"></i> {{ profile_user.username }} hasn't written a bio yet.</p>
|
|
{% endif %}
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="home-section">
|
|
<div class="home-section-header">
|
|
<h2>Packs by {{ profile_user.username }}</h2>
|
|
</div>
|
|
<div class="pack-grid">
|
|
{% for project in projects %}
|
|
{% include 'library/_project_card.html' %}
|
|
{% empty %}
|
|
<div class="pack-card pack-card-empty">
|
|
<div class="pack-card-thumb">
|
|
<i class="fas fa-box-open"></i>
|
|
</div>
|
|
<div class="pack-card-body">
|
|
<h3>No packs yet</h3>
|
|
<p class="pack-card-desc">This creator hasn't published anything yet.</p>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
{% if can_impersonate %}
|
|
<script>
|
|
(function () {
|
|
const btn = document.getElementById('impersonate-btn');
|
|
if (!btn) return;
|
|
btn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const reason = prompt('Reason for impersonation (optional):', '');
|
|
if (reason === null) return;
|
|
const form = btn.closest('form');
|
|
if (reason.trim()) {
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'reason';
|
|
input.value = reason.trim();
|
|
form.appendChild(input);
|
|
}
|
|
form.submit();
|
|
});
|
|
})();
|
|
</script>
|
|
{% endif %}
|
|
{% if is_owner %}
|
|
<script>
|
|
(function () {
|
|
const textarea = document.getElementById('{{ bio_form.bio.id_for_label }}');
|
|
const preview = document.getElementById('bio-preview');
|
|
const toggleBtn = document.querySelector('[data-bio-toggle]');
|
|
if (!textarea || !preview || !toggleBtn) return;
|
|
|
|
const url = "{% url 'profiles:bio_preview' %}";
|
|
let timer = null;
|
|
|
|
function refreshPreview() {
|
|
fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': getCookie('csrftoken'),
|
|
'Accept': 'application/json',
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: 'bio=' + encodeURIComponent(textarea.value),
|
|
})
|
|
.then(r => r.json())
|
|
.then(data => { preview.innerHTML = data.html; })
|
|
.catch(() => { preview.innerHTML = '<p><em>Preview unavailable.</em></p>'; });
|
|
}
|
|
|
|
toggleBtn.addEventListener('click', () => {
|
|
if (preview.hidden) {
|
|
preview.hidden = false;
|
|
toggleBtn.textContent = 'Hide preview';
|
|
refreshPreview();
|
|
} else {
|
|
preview.hidden = true;
|
|
toggleBtn.textContent = 'Preview';
|
|
}
|
|
});
|
|
|
|
textarea.addEventListener('input', () => {
|
|
if (preview.hidden) return;
|
|
clearTimeout(timer);
|
|
timer = setTimeout(refreshPreview, 300);
|
|
});
|
|
})();
|
|
</script>
|
|
{% endif %}
|
|
{% endblock %}
|