Update web/core/views_user_features.py
This commit is contained in:
parent
f75cb316b4
commit
641e09c1fe
@ -33,23 +33,28 @@ def api_get_prefs(request):
|
|||||||
# ---------- Search history ----------
|
# ---------- Search history ----------
|
||||||
# We use Beacon here, so CSRF headers aren’t available -> mark this one csrf_exempt
|
# We use Beacon here, so CSRF headers aren’t available -> mark this one csrf_exempt
|
||||||
@login_required
|
@login_required
|
||||||
@csrf_exempt
|
@csrf_exempt # keep this since you use sendBeacon
|
||||||
@require_POST
|
@require_POST
|
||||||
def api_log_search(request):
|
def api_log_search(request):
|
||||||
q = (request.POST.get("q") or "").strip()
|
q = (request.POST.get("q") or "").strip()
|
||||||
# Expect JSON-like dict from the client for fields, but we’ll accept a flat form too
|
|
||||||
|
# Collect selected fields from form-style keys: sel[subject]=on
|
||||||
selected = {}
|
selected = {}
|
||||||
for k in request.POST:
|
for k in request.POST:
|
||||||
if k.startswith("sel[") and k.endswith("]"): # sel[subject]=on
|
if k.startswith("sel[") and k.endswith("]"):
|
||||||
name = k[4:-1]
|
name = k[4:-1]
|
||||||
selected[name] = request.POST.get(k) in ("1", "true", "on", "yes")
|
selected[name] = request.POST.get(k) in ("1", "true", "on", "yes")
|
||||||
|
|
||||||
# consecutive de-duplication
|
# De-dupe consecutive identical searches; if identical, bump timestamp
|
||||||
last = SearchHistory.objects.filter(user=request.user).order_by("-created_at").first()
|
last = SearchHistory.objects.filter(user=request.user).order_by("-created_at").first()
|
||||||
if not last or last.q != q or last.selected != selected:
|
if last and last.q == q and last.selected == selected:
|
||||||
|
# bump to "most recent"
|
||||||
|
last.created_at = timezone.now()
|
||||||
|
last.save(update_fields=["created_at"])
|
||||||
|
else:
|
||||||
SearchHistory.objects.create(user=request.user, q=q, selected=selected)
|
SearchHistory.objects.create(user=request.user, q=q, selected=selected)
|
||||||
|
|
||||||
# trim to last 10
|
# Trim to last 10
|
||||||
ids = list(
|
ids = list(
|
||||||
SearchHistory.objects.filter(user=request.user)
|
SearchHistory.objects.filter(user=request.user)
|
||||||
.order_by("-created_at")
|
.order_by("-created_at")
|
||||||
@ -61,15 +66,21 @@ def api_log_search(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@require_GET
|
@require_GET
|
||||||
|
@never_cache
|
||||||
def api_get_search_history(request):
|
def api_get_search_history(request):
|
||||||
items = (
|
items_qs = (
|
||||||
SearchHistory.objects.filter(user=request.user)
|
SearchHistory.objects.filter(user=request.user)
|
||||||
.order_by("-created_at")
|
.order_by("-created_at")
|
||||||
.values("q", "selected", "created_at")
|
.values("q", "selected", "created_at")
|
||||||
)
|
)
|
||||||
# JSON-safe
|
data = [
|
||||||
data = [{"q": i["q"], "selected": i["selected"], "ts": i["created_at"].isoformat()} for i in items]
|
{"q": i["q"], "selected": i["selected"], "ts": i["created_at"].isoformat()}
|
||||||
return JsonResponse({"ok": True, "items": data})
|
for i in items_qs
|
||||||
|
]
|
||||||
|
resp = JsonResponse({"ok": True, "items": data})
|
||||||
|
resp["Cache-Control"] = "no-store"
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---------- Recently viewed ----------
|
# ---------- Recently viewed ----------
|
||||||
@ -83,7 +94,7 @@ def api_log_view(request, entry_id):
|
|||||||
|
|
||||||
ViewedIllustration.objects.create(user=request.user, entry=e)
|
ViewedIllustration.objects.create(user=request.user, entry=e)
|
||||||
|
|
||||||
# trim to 50
|
# Keep only the 50 most recent
|
||||||
ids = list(
|
ids = list(
|
||||||
ViewedIllustration.objects.filter(user=request.user)
|
ViewedIllustration.objects.filter(user=request.user)
|
||||||
.order_by("-viewed_at")
|
.order_by("-viewed_at")
|
||||||
@ -95,18 +106,31 @@ def api_log_view(request, entry_id):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@require_GET
|
@require_GET
|
||||||
|
@never_cache
|
||||||
def api_get_recent_views(request):
|
def api_get_recent_views(request):
|
||||||
rows = (
|
rows = (
|
||||||
ViewedIllustration.objects.filter(user=request.user)
|
ViewedIllustration.objects.filter(user=request.user)
|
||||||
.select_related("entry")
|
.select_related("entry")
|
||||||
.order_by("-viewed_at")[:10] # show 10 (we store 50)
|
.order_by("-viewed_at")[:10]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def first_words(text, n=20):
|
||||||
|
import re as _re
|
||||||
|
clean = _re.sub(r"\s+", " ", (text or "")).strip()
|
||||||
|
if not clean:
|
||||||
|
return ""
|
||||||
|
words = clean.split(" ")
|
||||||
|
return clean if len(words) <= n else " ".join(words[:n]) + "…"
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
"entry_id": r.entry_id,
|
"entry_id": r.entry_id,
|
||||||
"viewed_at": r.viewed_at.isoformat(),
|
"viewed_at": r.viewed_at.isoformat(),
|
||||||
"subject": (r.entry.subject or ""),
|
"illustration": r.entry.illustration or "", # <-- what the UI expects
|
||||||
|
"snippet": first_words(r.entry.illustration or "", 20),
|
||||||
}
|
}
|
||||||
for r in rows
|
for r in rows
|
||||||
]
|
]
|
||||||
return JsonResponse({"ok": True, "items": data})
|
resp = JsonResponse({"ok": True, "items": data})
|
||||||
|
resp["Cache-Control"] = "no-store"
|
||||||
|
return resp
|
||||||
Loading…
Reference in New Issue
Block a user