lib.itmens/journal/views/collection.py

415 lines
14 KiB
Python
Raw Normal View History

2023-08-10 14:56:38 -04:00
from django.contrib.auth.decorators import login_required
2024-07-01 17:29:38 -04:00
from django.core.exceptions import BadRequest, PermissionDenied
from django.http import HttpResponse, HttpResponseRedirect
2023-08-10 14:56:38 -04:00
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
2024-06-07 22:29:10 -04:00
from django.utils.translation import gettext as _
2024-04-23 23:57:49 -04:00
from django.views.decorators.http import require_http_methods
2023-08-10 14:56:38 -04:00
2023-07-20 21:59:49 -04:00
from catalog.models import Item
2024-12-30 01:51:19 -05:00
from common.models import int_
2023-07-20 21:59:49 -04:00
from common.utils import AuthedHttpRequest, get_uuid_or_404
2024-07-01 17:29:38 -04:00
from users.models import User
2023-08-10 14:56:38 -04:00
from ..forms import *
from ..models import *
2023-07-20 21:59:49 -04:00
from .common import render_relogin, target_identity_required
2023-08-10 14:56:38 -04:00
@login_required
2023-07-20 21:59:49 -04:00
def add_to_collection(request: AuthedHttpRequest, item_uuid):
2023-08-10 14:56:38 -04:00
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
if request.method == "GET":
2023-07-20 21:59:49 -04:00
collections = Collection.objects.filter(owner=request.user.identity)
2023-08-10 14:56:38 -04:00
return render(
request,
"add_to_collection.html",
{
"item": item,
"collections": collections,
},
)
else:
2024-12-30 01:51:19 -05:00
cid = int_(request.POST.get("collection_id"))
2023-08-10 14:56:38 -04:00
if not cid:
cid = Collection.objects.create(
2024-03-24 22:28:22 -04:00
owner=request.user.identity,
title=_("Collection by {0}").format(request.user.display_name),
).pk
2023-07-20 21:59:49 -04:00
collection = Collection.objects.get(owner=request.user.identity, id=cid)
2023-08-10 14:56:38 -04:00
collection.append_item(item, note=request.POST.get("note"))
2023-07-20 21:59:49 -04:00
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
2023-08-10 14:56:38 -04:00
2023-12-26 18:57:09 -05:00
def collection_retrieve_redirect(request: AuthedHttpRequest, collection_uuid):
return redirect(f"/collection/{collection_uuid}", permanent=True)
2023-07-20 21:59:49 -04:00
def collection_retrieve(request: AuthedHttpRequest, collection_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_visible_to(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
follower_count = collection.likes.all().count()
following = (
2023-08-13 23:11:12 -04:00
Like.user_liked_piece(request.user.identity, collection)
2023-08-10 14:56:38 -04:00
if request.user.is_authenticated
else False
)
featured_since = (
2023-07-20 21:59:49 -04:00
collection.featured_since(request.user.identity)
2023-08-10 14:56:38 -04:00
if request.user.is_authenticated
else None
)
available_as_featured = (
request.user.is_authenticated
2023-07-20 21:59:49 -04:00
and (following or request.user.identity == collection.owner)
2023-08-10 14:56:38 -04:00
and not featured_since
and collection.members.all().exists()
)
stats = {}
if featured_since:
2023-07-20 21:59:49 -04:00
stats = collection.get_stats(request.user.identity)
2023-08-10 14:56:38 -04:00
stats["wishlist_deg"] = (
round(stats["wishlist"] / stats["total"] * 360) if stats["total"] else 0
)
stats["progress_deg"] = (
round(stats["progress"] / stats["total"] * 360) if stats["total"] else 0
)
stats["complete_deg"] = (
round(stats["complete"] / stats["total"] * 360) if stats["total"] else 0
)
return render(
request,
"collection.html",
{
"collection": collection,
"follower_count": follower_count,
"following": following,
"stats": stats,
"available_as_featured": available_as_featured,
"featured_since": featured_since,
2023-08-13 23:11:12 -04:00
"editable": collection.is_editable_by(request.user),
2023-08-10 14:56:38 -04:00
},
)
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_add_featured(request: AuthedHttpRequest, collection_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_visible_to(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-07-20 21:59:49 -04:00
FeaturedCollection.objects.update_or_create(
owner=request.user.identity, target=collection
)
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
2023-08-10 14:56:38 -04:00
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_remove_featured(request: AuthedHttpRequest, collection_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_visible_to(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
fc = FeaturedCollection.objects.filter(
2023-07-20 21:59:49 -04:00
owner=request.user.identity, target=collection
2023-08-10 14:56:38 -04:00
).first()
if fc:
fc.delete()
2023-07-20 21:59:49 -04:00
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
2023-08-10 14:56:38 -04:00
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST", "GET"])
2023-07-20 21:59:49 -04:00
def collection_share(request: AuthedHttpRequest, collection_uuid):
collection = get_object_or_404(
Collection, uid=get_uuid_or_404(collection_uuid) if collection_uuid else None
2023-08-10 14:56:38 -04:00
)
2024-07-01 17:29:38 -04:00
user = request.user
if collection and not collection.is_visible_to(user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
if request.method == "GET":
return render(request, "collection_share.html", {"collection": collection})
2024-04-23 23:57:49 -04:00
else:
2024-07-01 17:29:38 -04:00
comment = request.POST.get("comment", "")
# boost if possible, otherwise quote
if (
not comment
2024-07-01 17:29:38 -04:00
and user.preference.mastodon_repost_mode == 0
and collection.latest_post
):
2024-07-01 17:29:38 -04:00
if user.mastodon:
user.mastodon.boost_later(collection.latest_post.url)
else:
2024-12-30 01:51:19 -05:00
visibility = VisibilityType(int_(request.POST.get("visibility")))
link = (
collection.latest_post.url
if collection.latest_post
else collection.absolute_url
2024-07-01 17:29:38 -04:00
) or ""
if not share_collection(collection, comment, user, visibility, link):
return render_relogin(request)
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
2023-08-10 14:56:38 -04:00
2024-07-01 17:29:38 -04:00
def share_collection(
collection: Collection,
comment: str,
user: User,
visibility: VisibilityType,
link: str,
):
if not user or not user.mastodon:
return
tags = (
"\n"
+ user.preference.mastodon_append_tag.replace("[category]", _("collection"))
if user.preference.mastodon_append_tag
else ""
)
user_str = (
_("shared my collection")
if user == collection.owner.user
else (
_("shared {username}'s collection").format(
username=(
2024-07-03 00:07:07 -04:00
" @" + collection.owner.user.mastodon.handle + " "
if collection.owner.user.mastodon
2024-07-01 17:29:38 -04:00
else " " + collection.owner.username + " "
)
)
)
)
content = f"{user_str}:{collection.title}\n{link}\n{comment}{tags}"
2024-07-03 16:42:20 -04:00
try:
user.mastodon.post(content, visibility)
2024-07-01 17:29:38 -04:00
return True
2024-07-03 16:42:20 -04:00
except Exception:
2024-07-01 17:29:38 -04:00
return False
2023-07-20 21:59:49 -04:00
def collection_retrieve_items(
request: AuthedHttpRequest, collection_uuid, edit=False, msg=None
):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_visible_to(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2025-01-20 10:21:57 -05:00
members = collection.ordered_members
last_pos = int_(request.GET.get("last_pos"))
if last_pos:
last_member = int_(request.GET.get("last_member"))
members = members.filter(position__gte=last_pos).exclude(id=last_member)
2023-08-10 14:56:38 -04:00
return render(
request,
"collection_items.html",
{
"collection": collection,
2025-01-20 10:21:57 -05:00
"members": members[:20],
2023-08-10 14:56:38 -04:00
"collection_edit": edit or request.GET.get("edit"),
"msg": msg,
},
)
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_append_item(request: AuthedHttpRequest, collection_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
2024-05-26 22:57:49 -04:00
url = request.POST.get("url", "")
note = request.POST.get("note", "")
2023-08-10 14:56:38 -04:00
item = Item.get_by_url(url)
member = None
2023-08-10 14:56:38 -04:00
if item:
member, new = collection.append_item(item, note=note)
if new:
collection.save()
msg = None
else:
member = None
msg = _("The item is already in the collection.")
2023-08-10 14:56:38 -04:00
else:
2024-03-24 22:28:22 -04:00
msg = _("Unable to find the item, please use item url from this site.")
return render(
request,
"collection_items.html",
{
"collection": collection,
"members": [member] if member else [],
"collection_edit": True,
"msg": msg,
},
)
2023-08-10 14:56:38 -04:00
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_remove_item(request: AuthedHttpRequest, collection_uuid, item_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
collection.remove_item(item)
return HttpResponse("")
2023-08-10 14:56:38 -04:00
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_move_item(
request: AuthedHttpRequest, direction, collection_uuid, item_uuid
):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
if direction == "up":
collection.move_up_item(item)
else:
collection.move_down_item(item)
return collection_retrieve_items(request, collection_uuid, True)
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["POST"])
2023-07-20 21:59:49 -04:00
def collection_update_member_order(request: AuthedHttpRequest, collection_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
ids = request.POST.get("member_ids", "").strip()
if not ids:
2024-04-23 23:57:49 -04:00
raise BadRequest(_("Invalid parameter"))
2024-12-30 01:51:19 -05:00
ordered_member_ids = [int_(i) for i in ids.split(",")]
2023-08-10 14:56:38 -04:00
collection.update_member_order(ordered_member_ids)
return render(
request,
"collection_items.html",
{
"collection": collection,
"members": [],
"collection_edit": True,
"msg": _("Saved."),
},
)
2023-08-10 14:56:38 -04:00
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["GET", "POST"])
2023-07-20 21:59:49 -04:00
def collection_update_item_note(request: AuthedHttpRequest, collection_uuid, item_uuid):
2023-08-10 14:56:38 -04:00
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
if not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
member = collection.get_member_for_item(item)
note = request.POST.get("note", default="")
cancel = request.GET.get("cancel")
if request.method == "POST" and member:
member.note = note # type: ignore
member.save()
return render(
request,
"collection_update_item_note_ok.html",
{"collection": collection, "item": item, "collection_member": member},
)
elif cancel:
return render(
request,
"collection_update_item_note_ok.html",
{"collection": collection, "item": item, "collection_member": member},
2023-08-10 14:56:38 -04:00
)
2024-04-23 23:57:49 -04:00
else:
2023-08-10 14:56:38 -04:00
return render(
request,
"collection_update_item_note.html",
{"collection": collection, "item": item, "collection_member": member},
2023-08-10 14:56:38 -04:00
)
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods(["GET", "POST"])
2023-07-20 21:59:49 -04:00
def collection_edit(request: AuthedHttpRequest, collection_uuid=None):
2023-08-10 14:56:38 -04:00
collection = (
get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if collection_uuid
else None
)
if collection and not collection.is_editable_by(request.user):
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Insufficient permission"))
2023-08-10 14:56:38 -04:00
if request.method == "GET":
form = CollectionForm(instance=collection) if collection else CollectionForm()
if request.GET.get("title"):
form.instance.title = request.GET.get("title")
return render(
request,
"collection_edit.html",
{
"form": form,
"collection": collection,
2023-07-20 21:59:49 -04:00
"user": collection.owner.user if collection else request.user,
2023-08-13 18:00:10 -04:00
"identity": collection.owner if collection else request.user.identity,
2023-08-10 14:56:38 -04:00
},
)
2024-04-23 23:57:49 -04:00
else:
2023-08-10 14:56:38 -04:00
form = (
CollectionForm(request.POST, request.FILES, instance=collection)
if collection
else CollectionForm(request.POST)
)
if form.is_valid():
if not collection:
2023-07-20 21:59:49 -04:00
form.instance.owner = request.user.identity
2023-08-10 14:56:38 -04:00
form.save()
return redirect(
reverse("journal:collection_retrieve", args=[form.instance.uuid])
)
else:
2024-04-23 23:57:49 -04:00
raise BadRequest(_("Invalid parameter"))
2023-08-10 14:56:38 -04:00
2023-07-20 21:59:49 -04:00
@target_identity_required
def user_collection_list(request: AuthedHttpRequest, user_name):
target = request.target_identity
if not request.user.is_authenticated and not target.anonymous_viewable:
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Login required"))
2023-12-31 09:54:59 -05:00
collections = (
Collection.objects.filter(owner=target)
.filter(q_owned_piece_visible_to_user(request.user, target))
.order_by("-edited_time")
2023-07-20 21:59:49 -04:00
)
2023-08-10 14:56:38 -04:00
return render(
request,
"user_collection_list.html",
{
2023-07-20 21:59:49 -04:00
"user": target.user,
2023-08-13 18:00:10 -04:00
"identity": target,
2023-08-10 14:56:38 -04:00
"collections": collections,
},
)
2023-07-20 21:59:49 -04:00
@target_identity_required
def user_liked_collection_list(request: AuthedHttpRequest, user_name):
target = request.target_identity
if not request.user.is_authenticated and not target.anonymous_viewable:
2024-04-23 23:57:49 -04:00
raise PermissionDenied(_("Login required"))
2023-12-27 16:23:46 -05:00
collections = Collection.objects.filter(
interactions__identity=target,
interactions__interaction_type="like",
interactions__target_type="Collection",
).order_by("-edited_time")
2023-07-20 21:59:49 -04:00
if target.user != request.user:
collections = collections.filter(q_piece_visible_to_user(request.user))
2023-08-10 14:56:38 -04:00
return render(
request,
"user_collection_list.html",
{
2023-07-20 21:59:49 -04:00
"user": target.user,
2023-08-13 18:00:10 -04:00
"identity": target,
2023-08-10 14:56:38 -04:00
"collections": collections,
"liked": True,
},
)