annoucment logic implemented, fixing looks

This commit is contained in:
JakeBreath
2026-08-05 15:50:32 -05:00
parent c163271a04
commit f5954247fc
22 changed files with 1020 additions and 18 deletions
@@ -0,0 +1,108 @@
{% extends 'base.html' %}
{% load markdown %}
{% block title %}{{ announcement.title }} - Packs Site{% endblock %}
{% block content %}
<div class="announce-detail">
<article class="card announce-card">
<h1>{{ announcement.title }}</h1>
<p class="announce-meta">
<i class="fas fa-user"></i> {{ announcement.created_by.username|default:"Staff" }}
<span class="separator"></span>
{{ announcement.created_at|date:"F j, Y, g:i a" }}
</p>
<div class="markdown-body">{{ announcement.body|markdown }}</div>
{% if user.is_staff %}
<div class="announce-admin">
<a href="{% url 'announcements:edit' announcement.pk %}" class="btn btn-secondary btn-sm"><i class="fas fa-edit"></i> Edit</a>
<form method="post" action="{% url 'announcements:delete' announcement.pk %}" class="inline" onsubmit="return confirm('Delete this announcement and all its comments?');">
{% csrf_token %}
<button type="submit" class="btn btn-secondary btn-sm"><i class="fas fa-trash"></i> Delete</button>
</form>
</div>
{% endif %}
</article>
<section class="card">
<h2><i class="fas fa-comments"></i> Discussion</h2>
{% if can_comment %}
<form method="post" action="{% url 'announcements:add_comment' announcement.pk %}" class="comment-form">
{% csrf_token %}
<textarea name="body" rows="4" placeholder="Write a comment… Markdown supported." required></textarea>
<button type="submit" class="btn btn-primary"><i class="fas fa-paper-plane"></i> Comment</button>
</form>
{% else %}
<p class="empty-hint"><a href="{% url 'profiles:login' %}?next={{ request.path }}" class="btn btn-secondary btn-sm">Log in</a> to join the discussion.</p>
{% endif %}
<div class="comment-list">
{% for comment in comments %}
<div class="comment" id="comment-{{ comment.pk }}">
<div class="comment-head">
<strong>{{ comment.user.username }}</strong>
<span class="comment-time">{{ comment.created_at|timesince }} ago</span>
{% if comment.updated_at != comment.created_at %}<span class="comment-edited">· edited</span>{% endif %}
{% if can_comment and comment.user == user %}
<span class="comment-actions">
<a href="#" class="comment-edit btn btn-secondary btn-sm" data-comment="{{ comment.pk }}"><i class="fas fa-edit"></i> Edit</a>
<form method="post" action="{% url 'announcements:delete_comment' announcement.pk comment.pk %}" class="inline">
{% csrf_token %}
<button type="submit" class="link-btn" title="Delete"><i class="fas fa-trash"></i></button>
</form>
</span>
{% elif can_comment and user.is_staff %}
<span class="comment-actions">
<form method="post" action="{% url 'announcements:delete_comment' announcement.pk comment.pk %}" class="inline" title="Delete this comment">
{% csrf_token %}
<button type="submit" class="btn btn-secondary btn-sm"><i class="fas fa-trash"></i> Delete</button>
</form>
</span>
{% endif %}
</div>
<div class="comment-body markdown-body">{{ comment.body|markdown }}</div>
{% if can_comment and comment.user == user %}
<form method="post" action="{% url 'announcements:edit_comment' announcement.pk comment.pk %}" class="comment-edit-form" data-comment="{{ comment.pk }}" hidden>
{% csrf_token %}
<textarea name="body" rows="3" required>{{ comment.body }}</textarea>
<div class="comment-edit-actions">
<button type="submit" class="btn btn-primary btn-sm">Save</button>
<button type="button" class="btn btn-secondary btn-sm comment-edit-cancel">Cancel</button>
</div>
</form>
{% endif %}
</div>
{% empty %}
<p class="empty-hint">No comments yet.</p>
{% endfor %}
</div>
</section>
</div>
{% endblock %}
{% block extra_js %}
<script>
(function () {
document.querySelectorAll('.comment-edit').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const id = link.dataset.comment;
const body = document.querySelector(`#comment-${id} .comment-body`);
const form = document.querySelector(`#comment-${id} .comment-edit-form`);
if (body) body.hidden = true;
if (form) form.hidden = false;
});
});
document.querySelectorAll('.comment-edit-cancel').forEach(btn => {
btn.addEventListener('click', () => {
const form = btn.closest('.comment-edit-form');
const id = form.dataset.comment;
const body = document.querySelector(`#comment-${id} .comment-body`);
if (body) body.hidden = false;
form.hidden = true;
});
});
})();
</script>
{% endblock %}
@@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block title %}{% if editing %}Edit announcement{% else %}New announcement{% endif %} - Packs Site{% endblock %}
{% block content %}
<h1>{% if editing %}<i class="fas fa-edit"></i> Edit announcement{% else %}<i class="fas fa-plus"></i> New announcement{% endif %}</h1>
<form method="post" class="announce-form">
{% csrf_token %}
{% if form.non_field_errors %}<div class="form-errors">{{ form.non_field_errors }}</div>{% endif %}
<div class="form-group">
{{ form.title.label_tag }}
{{ form.title.errors }}
{{ form.title }}
</div>
<div class="form-group">
{{ form.body.label_tag }}
{{ form.body.errors }}
{{ form.body }}
<p class="bio-help"><i class="fas fa-info-circle"></i> Supports Markdown — headings, lists, links, code, tables and more.</p>
</div>
<div class="form-group">
<label>
{{ form.published }}
Publish (visible to everyone)
</label>
</div>
<div class="announce-form-actions">
<button type="submit" class="btn btn-primary">{% if editing %}Save changes{% else %}Publish{% endif %}</button>
<a href="{% if editing %}{% url 'announcements:detail' announcement.pk %}{% else %}{% url 'announcements:list' %}{% endif %}" class="btn btn-secondary">Cancel</a>
</div>
</form>
{% endblock %}
@@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% load markdown %}
{% block title %}Announcements - Packs Site{% endblock %}
{% block content %}
<div class="home-section-header">
<h1><i class="fas fa-bullhorn"></i> Announcements</h1>
{% if user.is_staff %}
<a href="{% url 'announcements:create' %}" class="btn btn-primary"><i class="fas fa-plus"></i> New announcement</a>
{% endif %}
</div>
<div class="announce-list">
{% for a in page %}
<article class="card announce-card">
<h2>
<a href="{% url 'announcements:detail' a.pk %}">{{ a.title }}</a>
{% if user.is_authenticated and a.pk not in read_ids %}
<span class="announce-badge">new</span>
{% endif %}
</h2>
<div class="markdown-body announce-excerpt">{{ a.body|markdown|truncatechars_html:320 }}</div>
<p class="announce-meta">
<i class="fas fa-user"></i> {{ a.created_by.username|default:"Staff" }}
<span class="separator"></span>
{{ a.created_at|date:"F j, Y" }}
<span class="separator"></span>
<i class="fas fa-comments"></i> {{ a.comments_count }} comment{{ a.comments_count|pluralize }}
</p>
</article>
{% empty %}
<p class="empty-hint">No announcements yet.</p>
{% endfor %}
</div>
{% if page.has_other_pages %}
<div class="pagination">
{% if page.has_previous %}
<a href="?page={{ page.previous_page_number }}">&laquo;</a>
{% endif %}
<span>Page {{ page.number }} of {{ page.paginator.num_pages }}</span>
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}">&raquo;</a>
{% endif %}
</div>
{% endif %}
{% endblock %}
@@ -0,0 +1,39 @@
{% extends 'base.html' %}
{% block title %}Your alerts - Packs Site{% endblock %}
{% block content %}
<div class="home-section-header">
<h1><i class="fas fa-bell"></i> Your alerts</h1>
<form method="post" action="{% url 'announcements:mark_all_read' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn btn-secondary"><i class="fas fa-check-double"></i> Mark all read</button>
</form>
</div>
<div class="card">
<ul class="notify-list">
{% for n in page %}
<li class="notify-item{% if not n.read %} notify-unread{% endif %}">
<a href="{% url 'library:project_detail' n.project.slug %}">{{ n.text }}</a>
<span class="announce-meta">{{ n.created_at|timesince }} ago{% if not n.read %} · <span class="notify-new">new</span>{% endif %}</span>
</li>
{% empty %}
<li class="empty-hint">You have no alerts yet.</li>
{% endfor %}
</ul>
</div>
{% if page.has_other_pages %}
<div class="pagination">
{% if page.has_previous %}
<a href="?page={{ page.previous_page_number }}">&laquo;</a>
{% endif %}
<span>Page {{ page.number }} of {{ page.paginator.num_pages }}</span>
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}">&raquo;</a>
{% endif %}
</div>
{% endif %}
{% endblock %}
+3
View File
@@ -45,6 +45,9 @@
<a href="{% url 'profiles:user_list' %}">
<i class="fas fa-users"></i><span class="nav-text"> Users</span>
</a>
<a href="{% url 'announcements:list' %}">
<i class="fas fa-bullhorn"></i><span class="nav-text"> Announcements</span>
</a>
{% endif %}
</nav>
</div>
+38 -1
View File
@@ -19,7 +19,44 @@
<div class="home-placeholder">
<h2><i class="fas fa-bullhorn"></i> Announcements</h2>
<p class="home-placeholder-text">Placeholder — news and updates will live here.</p>
<div class="announce-panel">
{% for a in announcements %}
<div class="announce-item{% if a.pk not in global_read_ids and user.is_authenticated %} announce-unread{% endif %}">
<a href="{% url 'announcements:detail' a.pk %}">{{ a.title }}</a>
<span class="announce-meta">{{ a.created_at|date:"M j" }}{% if a.comments_count %} · {{ a.comments_count }} comment{{ a.comments_count|pluralize }}{% endif %}</span>
</div>
{% empty %}
<p class="empty-hint">No announcements yet.</p>
{% endfor %}
</div>
{% if announcements_total > 4 %}
<a href="{% url 'announcements:list' %}" class="announce-more">View all ({{ announcements_total }}) <i class="fas fa-arrow-right"></i></a>
{% endif %}
{% if user.is_authenticated %}
<h2 class="announce-subhead"><i class="fas fa-bell"></i> For you
{% if unread_notifications %}<span class="announce-badge">{{ unread_notifications }}</span>{% endif %}
</h2>
<div class="announce-panel">
{% for n in notifications %}
<div class="announce-item{% if not n.read %} announce-unread{% endif %}">
<a href="{% url 'library:project_detail' n.project.slug %}">{{ n.text }}</a>
<span class="announce-meta">{{ n.created_at|timesince }} ago</span>
</div>
{% empty %}
<p class="empty-hint">Nothing new for you yet.</p>
{% endfor %}
</div>
<div class="announce-actions">
<a href="{% url 'announcements:personal' %}" class="announce-more">All your alerts <i class="fas fa-arrow-right"></i></a>
{% if unread_notifications %}
<form method="post" action="{% url 'announcements:mark_all_read' %}">
{% csrf_token %}
<button type="submit" class="link-btn">Mark all read</button>
</form>
{% endif %}
</div>
{% endif %}
</div>
<div class="home-stats">