feat(tags): fandom-less character nudges
Adds a header counter ('⚠ N characters need a fandom') that filters to
?null_fandom=1, plus an inline chip on each qualifying character card.
Backend accepts null_fandom_only in the list query.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+26
-9
@@ -440,7 +440,7 @@ def gallery_jump():
|
||||
)
|
||||
|
||||
|
||||
def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, search=None):
|
||||
def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, search=None, null_fandom_only=False):
|
||||
"""
|
||||
Helper function to get tags with counts and preview images.
|
||||
Returns (tag_data list, total_count, has_more).
|
||||
@@ -455,6 +455,8 @@ def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, sea
|
||||
count_q = count_q.filter(Tag.kind == kind)
|
||||
if search:
|
||||
count_q = count_q.filter(Tag.name.ilike(f'%{search}%'))
|
||||
if null_fandom_only:
|
||||
count_q = count_q.filter(Tag.kind == 'character', Tag.fandom_id.is_(None))
|
||||
total_count = count_q.scalar()
|
||||
|
||||
# Query 1: Get tags with image counts (paginated)
|
||||
@@ -467,6 +469,8 @@ def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, sea
|
||||
q = q.filter(Tag.kind == kind)
|
||||
if search:
|
||||
q = q.filter(Tag.name.ilike(f'%{search}%'))
|
||||
if null_fandom_only:
|
||||
q = q.filter(Tag.kind == 'character', Tag.fandom_id.is_(None))
|
||||
|
||||
tags_with_counts = q.order_by(Tag.name.asc()).offset(offset).limit(limit).all()
|
||||
|
||||
@@ -481,6 +485,7 @@ def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, sea
|
||||
"tag": t.name,
|
||||
"images": [],
|
||||
"kind": t.kind,
|
||||
"fandom_id": t.fandom_id,
|
||||
"count": count
|
||||
}
|
||||
|
||||
@@ -524,20 +529,28 @@ def _get_tags_with_previews(kind=None, limit=35, offset=0, images_per_tag=3, sea
|
||||
def tag_list():
|
||||
"""
|
||||
Generic tag explorer with infinite scroll:
|
||||
/tags -> all tags
|
||||
/tags?kind=user -> only user tags
|
||||
/tags?search=xyz -> tags matching search term
|
||||
etc.
|
||||
/tags -> all tags
|
||||
/tags?kind=user -> only user tags
|
||||
/tags?search=xyz -> tags matching search term
|
||||
/tags?null_fandom=1 -> only fandom-less character tags
|
||||
Shows a few preview images per tag.
|
||||
Initially loads 35 tags, more loaded via API as user scrolls.
|
||||
"""
|
||||
kind = request.args.get('kind')
|
||||
search = request.args.get('search', '').strip() or None
|
||||
null_fandom_only = request.args.get('null_fandom') == '1'
|
||||
limit = 35
|
||||
images_per_tag = 3
|
||||
|
||||
tag_data, total_count, has_more = _get_tags_with_previews(
|
||||
kind=kind, limit=limit, offset=0, images_per_tag=images_per_tag, search=search
|
||||
kind=kind, limit=limit, offset=0, images_per_tag=images_per_tag,
|
||||
search=search, null_fandom_only=null_fandom_only
|
||||
)
|
||||
|
||||
null_fandom_character_count = (
|
||||
db.session.query(func.count(Tag.id))
|
||||
.filter(Tag.kind == 'character', Tag.fandom_id.is_(None))
|
||||
.scalar() or 0
|
||||
)
|
||||
|
||||
return render_template('tags_list.html',
|
||||
@@ -547,7 +560,9 @@ def tag_list():
|
||||
search_query=search or '',
|
||||
total_count=total_count,
|
||||
has_more=has_more,
|
||||
page_size=limit)
|
||||
page_size=limit,
|
||||
null_fandom_character_count=null_fandom_character_count,
|
||||
show_null_fandom_filter=null_fandom_only)
|
||||
|
||||
|
||||
@main.route('/api/tags/list')
|
||||
@@ -558,16 +573,18 @@ def api_tags_list():
|
||||
"""
|
||||
kind = request.args.get('kind')
|
||||
search = request.args.get('search', '').strip() or None
|
||||
null_fandom_only = request.args.get('null_fandom') == '1'
|
||||
offset = request.args.get('offset', 0, type=int)
|
||||
limit = request.args.get('limit', 35, type=int)
|
||||
images_per_tag = 3
|
||||
|
||||
tag_data, total_count, has_more = _get_tags_with_previews(
|
||||
kind=kind, limit=limit, offset=offset, images_per_tag=images_per_tag, search=search
|
||||
kind=kind, limit=limit, offset=offset, images_per_tag=images_per_tag,
|
||||
search=search, null_fandom_only=null_fandom_only
|
||||
)
|
||||
|
||||
# Render tag cards to HTML
|
||||
cards_html = render_template('_tag_cards.html', tag_data=tag_data)
|
||||
cards_html = render_template('_tag_cards.html', tag_data=tag_data, show_null_fandom_filter=null_fandom_only)
|
||||
|
||||
return jsonify(
|
||||
ok=True,
|
||||
|
||||
Reference in New Issue
Block a user