feat: add leaderboard router, gamification backfill, and shared content creation helpers
Introduce a new `/leaderboard` endpoint ranking top 50 members by total stars, wire it into the app router and documentation. Implement `_backfill_gamification()` in `database.py` to compute XP/levels for existing accounts from prior posts, comments, votes, and follows. Extract `is_owner()`, `create_content_item()`, and `detail_context()` into `content.py` to centralize content creation, reward awarding, mention notifications, and attachment linking. Update comment creation/deletion in `comments.py` to use `award_rewards()` with `XP_COMMENT` and the new `is_owner()` helper. Add shared template partials documentation for vote bars, star buttons, post headers, and topic selectors to `AGENTS.md`.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "_macros.html" import modal %}
|
||||
{% block extra_head %}
|
||||
<link rel="stylesheet" href="/static/css/gists.css">
|
||||
<link rel="stylesheet" href="/static/css/post.css">
|
||||
@@ -45,10 +46,7 @@
|
||||
<div class="gist-detail-actions">
|
||||
<button type="button" class="gist-star-btn" data-share="/gists/{{ gist['slug'] or gist['uid'] }}">🔗 Share</button>
|
||||
{% if user %}
|
||||
<form method="POST" action="/votes/gist/{{ gist['uid'] }}" style="display:inline;">
|
||||
<input type="hidden" name="value" value="1">
|
||||
<button type="submit" class="gist-star-btn">☆ <span class="vote-count-value" data-vote-count="{{ gist['uid'] }}">{{ star_count }}</span></button>
|
||||
</form>
|
||||
{% set _type = "gist" %}{% set _uid = gist['uid'] %}{% set _my_vote = my_vote %}{% set _count = star_count %}{% set _btn_class = "gist-star-btn" %}{% include "_star_vote.html" %}
|
||||
{% endif %}
|
||||
{% if is_owner %}
|
||||
<button class="gist-star-btn" data-modal="edit-gist-modal"><span class="icon">✏️</span>Edit</button>
|
||||
@@ -60,12 +58,7 @@
|
||||
</article>
|
||||
|
||||
{% if is_owner %}
|
||||
<div class="modal-overlay" id="edit-gist-modal">
|
||||
<div class="card modal-card modal-card-wide">
|
||||
<div class="modal-header">
|
||||
<h3>Edit Gist</h3>
|
||||
<button type="button" class="modal-close btn-ghost btn-icon modal-close-btn">×</button>
|
||||
</div>
|
||||
{% call modal('edit-gist-modal', 'Edit Gist', wide=true) %}
|
||||
<form method="POST" action="/gists/edit/{{ gist['slug'] or gist['uid'] }}">
|
||||
<div class="auth-field auth-field-gap">
|
||||
<label for="edit-gist-title">Title</label>
|
||||
@@ -93,8 +86,7 @@
|
||||
<button type="submit" class="btn btn-primary"><span class="icon">💾</span>Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% with target_uid=gist['uid'], target_type="gist" %}
|
||||
|
||||
Reference in New Issue
Block a user