forked from retoor/devplacepy
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:
@@ -2,85 +2,6 @@
|
||||
{% block extra_head %}
|
||||
<link rel="stylesheet" href="/static/css/projects.css">
|
||||
<link rel="stylesheet" href="/static/css/post.css">
|
||||
<style>
|
||||
.project-detail-page {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.project-detail {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1.5rem;
|
||||
}
|
||||
.project-detail-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.project-detail-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
.project-detail-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.project-detail-meta span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
.project-detail-author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.project-detail-author a {
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.project-detail-desc {
|
||||
font-size: 0.9375rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.project-detail-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.project-star-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
border-radius: var(--radius);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.project-star-btn:hover {
|
||||
background: var(--bg-card-hover);
|
||||
color: var(--warning);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="project-detail-page">
|
||||
@@ -134,10 +55,7 @@
|
||||
<div class="project-detail-actions">
|
||||
<button type="button" class="project-star-btn" data-share="/projects/{{ project['slug'] or project['uid'] }}">🔗 Share</button>
|
||||
{% if user %}
|
||||
<form method="POST" action="/votes/project/{{ project['uid'] }}" style="display:inline;">
|
||||
<input type="hidden" name="value" value="1">
|
||||
<button type="submit" class="project-star-btn">☆ <span class="vote-count-value" data-vote-count="{{ project['uid'] }}">{{ star_count }}</span></button>
|
||||
</form>
|
||||
{% set _type = "project" %}{% set _uid = project['uid'] %}{% set _my_vote = my_vote %}{% set _count = star_count %}{% set _btn_class = "project-star-btn" %}{% include "_star_vote.html" %}
|
||||
{% endif %}
|
||||
{% if is_owner %}
|
||||
<form method="POST" action="/projects/delete/{{ project['slug'] or project['uid'] }}" style="display:inline;">
|
||||
|
||||
Reference in New Issue
Block a user