from django.contrib.auth.decorators import login_required from django.db.models import QuerySet from django.http import HttpResponseRedirect, Http404, HttpResponseBadRequest from django.shortcuts import render from django.urls import reverse from bookmarks import queries from bookmarks.models import Bookmark, BookmarkForm, BookmarkSearch, build_tag_string from bookmarks.services.bookmarks import create_bookmark, update_bookmark, archive_bookmark, archive_bookmarks, \ unarchive_bookmark, unarchive_bookmarks, delete_bookmarks, tag_bookmarks, untag_bookmarks, mark_bookmarks_as_read, \ mark_bookmarks_as_unread, share_bookmarks, unshare_bookmarks from bookmarks.utils import get_safe_return_url from bookmarks.views.partials import contexts _default_page_size = 30 @login_required def index(request): bookmark_list = contexts.ActiveBookmarkListContext(request) tag_cloud = contexts.ActiveTagCloudContext(request) return render(request, 'bookmarks/index.html', { 'bookmark_list': bookmark_list, 'tag_cloud': tag_cloud, }) @login_required def archived(request): bookmark_list = contexts.ArchivedBookmarkListContext(request) tag_cloud = contexts.ArchivedTagCloudContext(request) return render(request, 'bookmarks/archive.html', { 'bookmark_list': bookmark_list, 'tag_cloud': tag_cloud, }) def shared(request): search = BookmarkSearch.from_request(request) bookmark_list = contexts.SharedBookmarkListContext(request) tag_cloud = contexts.SharedTagCloudContext(request) public_only = not request.user.is_authenticated users = queries.query_shared_bookmark_users(request.user_profile, search, public_only) return render(request, 'bookmarks/shared.html', { 'bookmark_list': bookmark_list, 'tag_cloud': tag_cloud, 'users': users }) def convert_tag_string(tag_string: str): # Tag strings coming from inputs are space-separated, however services.bookmarks functions expect comma-separated # strings return tag_string.replace(' ', ',') @login_required def new(request): initial_url = request.GET.get('url') initial_title = request.GET.get('title') initial_description = request.GET.get('description') initial_auto_close = 'auto_close' in request.GET if request.method == 'POST': form = BookmarkForm(request.POST) auto_close = form.data['auto_close'] if form.is_valid(): current_user = request.user tag_string = convert_tag_string(form.data['tag_string']) create_bookmark(form.save(commit=False), tag_string, current_user) if auto_close: return HttpResponseRedirect(reverse('bookmarks:close')) else: return HttpResponseRedirect(reverse('bookmarks:index')) else: form = BookmarkForm() if initial_url: form.initial['url'] = initial_url if initial_title: form.initial['title'] = initial_title if initial_description: form.initial['description'] = initial_description if initial_auto_close: form.initial['auto_close'] = 'true' context = { 'form': form, 'auto_close': initial_auto_close, 'return_url': reverse('bookmarks:index') } return render(request, 'bookmarks/new.html', context) @login_required def edit(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') return_url = get_safe_return_url(request.GET.get('return_url'), reverse('bookmarks:index')) if request.method == 'POST': form = BookmarkForm(request.POST, instance=bookmark) if form.is_valid(): tag_string = convert_tag_string(form.data['tag_string']) update_bookmark(form.save(commit=False), tag_string, request.user) return HttpResponseRedirect(return_url) else: form = BookmarkForm(instance=bookmark) form.initial['tag_string'] = build_tag_string(bookmark.tag_names, ' ') context = { 'form': form, 'bookmark_id': bookmark_id, 'return_url': return_url } return render(request, 'bookmarks/edit.html', context) def remove(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') bookmark.delete() def archive(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') archive_bookmark(bookmark) def unarchive(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') unarchive_bookmark(bookmark) def unshare(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') bookmark.shared = False bookmark.save() def mark_as_read(request, bookmark_id: int): try: bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user) except Bookmark.DoesNotExist: raise Http404('Bookmark does not exist') bookmark.unread = False bookmark.save() @login_required def index_action(request): search = BookmarkSearch.from_request(request) query = queries.query_bookmarks(request.user, request.user_profile, search) return action(request, query) @login_required def archived_action(request): search = BookmarkSearch.from_request(request) query = queries.query_archived_bookmarks(request.user, request.user_profile, search) return action(request, query) @login_required def shared_action(request): return action(request) def action(request, query: QuerySet[Bookmark] = None): # Single bookmark actions if 'archive' in request.POST: archive(request, request.POST['archive']) if 'unarchive' in request.POST: unarchive(request, request.POST['unarchive']) if 'remove' in request.POST: remove(request, request.POST['remove']) if 'mark_as_read' in request.POST: mark_as_read(request, request.POST['mark_as_read']) if 'unshare' in request.POST: unshare(request, request.POST['unshare']) # Bulk actions if 'bulk_execute' in request.POST: if query is None: return HttpResponseBadRequest('View does not support bulk actions') bulk_action = request.POST['bulk_action'] # Determine set of bookmarks if request.POST.get('bulk_select_across') == 'on': # Query full list of bookmarks across all pages bookmark_ids = query.only('id').values_list('id', flat=True) else: # Use only selected bookmarks bookmark_ids = request.POST.getlist('bookmark_id') if 'bulk_archive' == bulk_action: archive_bookmarks(bookmark_ids, request.user) if 'bulk_unarchive' == bulk_action: unarchive_bookmarks(bookmark_ids, request.user) if 'bulk_delete' == bulk_action: delete_bookmarks(bookmark_ids, request.user) if 'bulk_tag' == bulk_action: tag_string = convert_tag_string(request.POST['bulk_tag_string']) tag_bookmarks(bookmark_ids, tag_string, request.user) if 'bulk_untag' == bulk_action: tag_string = convert_tag_string(request.POST['bulk_tag_string']) untag_bookmarks(bookmark_ids, tag_string, request.user) if 'bulk_read' == bulk_action: mark_bookmarks_as_read(bookmark_ids, request.user) if 'bulk_unread' == bulk_action: mark_bookmarks_as_unread(bookmark_ids, request.user) if 'bulk_share' == bulk_action: share_bookmarks(bookmark_ids, request.user) if 'bulk_unshare' == bulk_action: unshare_bookmarks(bookmark_ids, request.user) return_url = get_safe_return_url(request.GET.get('return_url'), reverse('bookmarks:index')) return HttpResponseRedirect(return_url) @login_required def close(request): return render(request, 'bookmarks/close.html')