def search(request): # if user is deleting a bookmark from search results if 'delete-bookmark-form' in request.POST: bookmark_utils.delete_bookmark(request) # Fetch form search query q = request.GET.get('q') q = "" if q is None else q results_per_page = 10 # find bookmarks based on search query search_qs = Bookmark.objects.filter( user=request.user, title__icontains=q ).order_by('added') # pagination results_page = request.GET.get('rpage', 1) paginator = Paginator(search_qs, results_per_page) try: search_results = paginator.page(results_page) except PageNotAnInteger: search_results = paginator.page(1) except EmptyPage: search_results = paginator.page(paginator.num_pages) # get pages for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') # set page value for default page choice for 'add bookmark' button page = set_page_name(request) # bookmark paramaters for use with the 'delete_modal' template bm_delete_modal = {"form_name": "delete-bookmark-form", "object_type": "bookmark", "text": "the bookmark will be permanently deleted.", } context = { "all_page_names": all_pages, "page": page, "q": q, "search_results": search_results, "p": paginator, "page_num": results_page, "bm_delete_modal": bm_delete_modal, } context = is_premium(request.user, context) return render(request, 'search/search_results.html', context)
def support(request): # if support form has been posted if request.method == "POST": form_data = SupportRequestForm(request.POST) if form_data.is_valid(): # save support form to db form = form_data.save(commit=False) form.user = request.user form.email = request.user.email form.save() html_message = render_to_string( 'support/support_email_template.html', {'title': form.title, 'message': form.message, 'username': form.user}) plain_message = strip_tags(html_message) # email user a copy of their support form send_mail(form.title, plain_message, 'Bookmark Team', [form.email], html_message=html_message ) messages.success( request, "Ticket created, we'll be in touch soon!") return redirect(reverse("support")) else: messages.error( request, f"There was an error with your form, \ please try again." ) support_request_form = form_data else: support_request_form = SupportRequestForm() # set page value for default page choice for 'add bookmark' button page = set_page_name(request) context = {'support_request_form': support_request_form, 'page': page, } context = is_premium(request.user, context) return render(request, 'support/support.html', context)
def about(request): # set page value for default page choice for 'add bookmark' button page = set_page_name(request) # get current year for copyright statement year = datetime.now().year context = { 'app_version': settings.LINKS_APP_VERSION, 'page': page, 'year': year, } context = is_premium(request.user, context) return render(request, 'accounts/about_app.html', context)
def arrange_collections(request, page): """ Display the collections on the page in a cleaner and more concise way (ie, just the collection names) to make it easier for the user to sort them into a preferred order. """ # check page exists, redirect if not try: page = Page.objects.get(user=request.user, name=page) except ObjectDoesNotExist: messages.error(request, f"Could not find a page with the name '{page}'.") return redirect('start_app') collections = Collection.objects.filter( user__username=request.user).filter( page__name=page.name).order_by('position') # get page names for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') num_of_columns = page.num_of_columns # generate collection names & order collection_list = collection_utils.make_collection_list( request, page, num_of_columns, collections) context = { "page": page.name, "num_of_columns": num_of_columns, "column_width": 100 / num_of_columns, "all_page_names": all_pages, "collection_data": collection_list, "num_of_collections": collections.count(), } context = is_premium(request.user, context) return render(request, 'links/arrange_collections.html', context)
def import_url(request): """ Import a URL using the chrome extension, scrape the sites metadata and save it all as a new bookmark object. """ url_to_save = request.GET.get('url') collection_count = Collection.objects.filter(user=request.user).count() # redirect if user attempts to access view directly if url_to_save is None: return redirect('start_app') # get page position 1 to set as default in dest_page choice field page = Page.objects.get(user=request.user, position=1) saved_icon_data = "" use_default_icon = "" # handle posted data if 'import-url-form' in request.POST: page = Page.objects.get(user=request.user, pk=request.POST.get('dest_page')) bookmark_form = BookmarkForm(request.POST, request.FILES) move_bookmark_form = MoveBookmarkForm(request.user, page, request.POST) if bookmark_form.is_valid() and move_bookmark_form.is_valid(): # create a new Bookmark object bookmark_utils.add_bookmark_object(request, bookmark_form) request.session['imported_url'] = url_to_save return redirect('import_url_success') else: icon_errors = bookmark_utils.handle_icon_errors( request, bookmark_form) if icon_errors: if icon_errors[0]: use_default_icon = True else: saved_icon_data = icon_errors[1] messages.error( request, f"There was an error with your form - \ please try again.") context = { "bookmark_form": bookmark_form, "move_bookmark_form": move_bookmark_form, "collection_count": collection_count, "saved_icon_data": saved_icon_data, "use_default_icon": use_default_icon, } context = is_premium(request.user, context) return render(request, 'links/import_url.html', context) bookmark_form = BookmarkForm(initial={ 'url': url_to_save, }) move_bookmark_form = MoveBookmarkForm(request.user, page, initial={'dest_page': page}) # set autoscrape var so on page load, app will scrape the imported url # ensures that on reload due to errors, page will not autoscrape again autoscrape = "true" context = { 'bookmark_form': bookmark_form, 'move_bookmark_form': move_bookmark_form, 'collection_count': collection_count, 'autoscrape': autoscrape, } context = is_premium(request.user, context) return render(request, 'links/import_url.html', context)
def move_bookmark(request, page, bookmark): """ Moves the requested bookmark to a page and collection chosen by the user. Updates the position values of the remaining bookmarks in the source collection and appends the moved bookmark to the end of the destination collection. """ # check destination page exists, and redirect if not. try: page = Page.objects.get(user=request.user, name=page) except ObjectDoesNotExist: messages.error(request, f"Could not find a page with the name '{page}'.") return redirect('start_app') # check bookmark to move exists, and redirect if not. Has the added # benefit of stopping users trying to move bookmarks that aren't theirs. try: bookmark_to_move = Bookmark.objects.get(user=request.user, pk=bookmark) except ObjectDoesNotExist: messages.error(request, f"Could not find the requested bookmark.") return redirect('start_app') move_bookmark_form = MoveBookmarkForm(request.user, page, initial={'dest_page': page}) # handle posted data if 'move-bm-form' in request.POST: page = Page.objects.get(user=request.user, pk=request.POST.get('dest_page')) move_bookmark_form = MoveBookmarkForm(request.user, page, request.POST) if move_bookmark_form.is_valid(): orig_collection = bookmark_to_move.collection dest_collection = Collection.objects.get( id=request.POST.get('dest_collection')) # get new position value for bookmark dest_position = Bookmark.objects.filter( user=request.user, collection=dest_collection).count() + 1 # update bookmark object with new collection & position bookmark_to_move.collection = dest_collection bookmark_to_move.position = dest_position bookmark_to_move.save() # Reapply position values to bookmarks in the original collection # to account for the gap made when moving the bookmark out orig_collection_to_reorder = Bookmark.objects.filter( user=request.user, collection=orig_collection).order_by('position') bookmark_utils.reorder_bookmarks(orig_collection_to_reorder) return redirect('links', page=page) # get page names for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') context = { "page": page.name, "bookmark": bookmark_to_move, "move_bookmark_form": move_bookmark_form, "all_page_names": all_pages, } context = is_premium(request.user, context) return render(request, 'links/move_bookmark.html', context)
def add_bookmark(request, page): """ Create a new Bookmark object """ # check allowed extra bookmark at current membership level check = premium_check(request, Bookmark, settings.LINKS_STND_MAX_BOOKMARKS) if not check: return redirect('premium') # check page exists, redirect to page at position 1 if not try: page = Page.objects.get(user=request.user, name=page) except ObjectDoesNotExist: page = Page.objects.get(user=request.user, position=1) return redirect('add_bookmark', page=page) collection_count = Collection.objects.filter(user=request.user).count() # initialize forms bookmark_form = BookmarkForm() # check if a collection destination has been specified bm_dest_collection = Collection.objects.filter( user=request.user, page=page, name=request.POST.get('dest-collection-name')).first() move_bookmark_form = MoveBookmarkForm(request.user, page, initial={ 'dest_page': page, 'dest_collection': bm_dest_collection }) saved_icon_data = "" use_default_icon = "" # handle posted data if 'add-bm-form' in request.POST: page = Page.objects.get(user=request.user, pk=request.POST.get('dest_page')) bookmark_form = BookmarkForm(request.POST, request.FILES) move_bookmark_form = MoveBookmarkForm(request.user, page, request.POST) if bookmark_form.is_valid() and move_bookmark_form.is_valid(): # create a new Bookmark object bookmark_utils.add_bookmark_object(request, bookmark_form) return redirect('links', page=page) else: icon_errors = bookmark_utils.handle_icon_errors( request, bookmark_form) if icon_errors: if icon_errors[0]: use_default_icon = True else: saved_icon_data = icon_errors[1] messages.error( request, f"There was an error with your form - \ please try again.") # get page names for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') context = { "bookmark_form": bookmark_form, "move_bookmark_form": move_bookmark_form, "collection_count": collection_count, "page": page.name, "all_page_names": all_pages, "saved_icon_data": saved_icon_data, "use_default_icon": use_default_icon, } context = is_premium(request.user, context) return render(request, 'links/add_bookmark.html', context)
def edit_bookmark(request, page, bookmark): """ Edit and update the requested Bookmark object """ # check page exists, redirect if not try: page = Page.objects.get(user=request.user, name=page) except ObjectDoesNotExist: messages.error(request, f"Could not find a page with the name '{page}'.") return redirect('start_app') # check bookmark to edit exists, redirect if not. Also stops users trying # to edit bookmarks that aren't theirs. try: bookmark_to_edit = Bookmark.objects.get(user=request.user, pk=bookmark) except ObjectDoesNotExist: # stop users trying to edit bookmarks that aren't theirs messages.error(request, f"Could not find the requested bookmark.") return redirect('start_app') bookmark_form = BookmarkForm(instance=bookmark_to_edit) saved_icon_data = "" use_default_icon = "" # handle posted data if 'edit-bm-form' in request.POST: bookmark_form = BookmarkForm(request.POST, request.FILES, instance=bookmark_to_edit) if bookmark_form.is_valid(): # check if scraped file is present form = bookmark_form.save(commit=False) if not request.FILES and request.POST.get('scraped_img'): # save image from scraped data form.icon = bookmark_utils.create_img_from_base64_str(request) if not request.FILES and \ not request.POST.get('scraped_img') and \ request.POST.get('use-default'): # if user has requested to use default icon, delete any stored # icon file form.icon = None form.save() return redirect('links', page=page) else: # for icon display, handle errors with icon if 'icon' in bookmark_form.errors: # override clean method, reset bookmark icon bookmark_to_edit.icon = Bookmark.objects.get(user=request.user, pk=bookmark).icon # for icon display, handle non icon errors else: icon_errors = bookmark_utils.handle_icon_errors( request, bookmark_form) if request.POST.get('use-default'): bookmark_to_edit.icon = None if icon_errors: if icon_errors[0]: use_default_icon = True else: saved_icon_data = icon_errors[1] messages.error( request, f"There was an error with your form - \ please try again.") # get page names for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') context = { "page": page.name, "bookmark": bookmark_to_edit, "bookmark_form": bookmark_form, "all_page_names": all_pages, "saved_icon_data": saved_icon_data, "use_default_icon": use_default_icon, } context = is_premium(request.user, context) return render(request, 'links/edit_bookmark.html', context)
def links(request, page): """ The main app view """ # check page exists, redirect if not try: page = Page.objects.get(user=request.user, name=page) except ObjectDoesNotExist: messages.error(request, f"Could not find a page with the name '{page}'.") return redirect('start_app') # get all collections & bookmarks for current page collections = Collection.objects.filter( user__username=request.user, page__name=page.name).order_by('position') bookmarks = Bookmark.objects.filter(user__username=request.user, collection__in=collections) # initialize forms add_new_page_form = AddNewPageForm(current_user=request.user, prefix='new_page', auto_id=False) edit_page_form = EditPageForm(current_user=request.user) # add new page form if 'add-page-form' in request.POST: # check allowed extra page at current membership level check = premium_check(request, Page, settings.LINKS_STND_MAX_PAGES) if check: form_data = AddNewPageForm(request.POST, current_user=request.user, prefix='new_page', auto_id=False) if form_data.is_valid(): new_page = page_utils.add_page(request, form_data) return redirect('links', page=new_page) else: add_new_page_form = form_data else: return redirect('premium') # edit page form if 'edit-page-form' in request.POST: form_data = EditPageForm(request.POST, current_user=request.user) if form_data.is_valid(): new_page_name = form_data.cleaned_data.get('name') page_utils.edit_page_name(request, new_page_name, page) return redirect('links', page=new_page_name) else: edit_page_form = form_data # delete page form if 'delete-page-form' in request.POST: page_utils.delete_page(request, page) # if no pages left, create a default page & redirect to it if not Page.objects.filter(user=request.user).exists(): messages.success( request, f"You must have at least 1 page. \ Creating a default page called 'Home'.") page_utils.create_default_page(request) # redirect to first page page = Page.objects.get(user=request.user, position=1) return redirect('links', page=page) # add new collection form if 'add-collection' in request.POST: # check allowed extra collection at current membership level check = premium_check(request, Collection, settings.LINKS_STND_MAX_COLLECTIONS) if check: # check name is allowed and if so, add to db proposed_name = request.POST.get('collection_name') if collection_utils.validate_name(request, proposed_name, collections, page): collection_utils.add_collection(request, page) return redirect('links', page=page) else: return redirect('premium') # rename collection form if 'rename-collection-form' in request.POST: collection_position = request.POST.get('collection-position') proposed_name = request.POST.get('new-collection-name') if collection_utils.validate_name(request, proposed_name, collections, page): collection_to_rename = get_object_or_404( Collection, user=request.user, page=page, position=int(collection_position)) collection_to_rename.name = proposed_name collection_to_rename.save() return redirect('links', page=page) # delete collection form if 'delete-collection-form' in request.POST: collection_utils.delete_collection(request, page, collections) return redirect('links', page=page) # delete bookmark form if 'delete-bookmark-form' in request.POST: bookmark_utils.delete_bookmark(request) return redirect('links', page=page) # get page names for sidebar all_pages = Page.objects.filter(user=request.user).order_by('position') # generate collection names & order num_of_columns = page.num_of_columns collection_list = collection_utils.make_collection_list( request, page, num_of_columns, collections) # create list of sort options sort_options = [ 'position', 'an_title', '-an_title', 'added', '-added', 'updated', '-updated' ] # iterate through collection names and create a qs of bookmarks for each bm_data = [] for x in range(num_of_columns): column = {} for j in (collection_list[x]): qs = bookmarks.filter(collection=j).annotate( an_title=Lower('title')).order_by((sort_options[j.sort_order])) column[j] = qs bm_data.append(column) # set collection_being_sorted var try: collection_being_sorted = request.session['collection_being_sorted'] del request.session['collection_being_sorted'] except KeyError: collection_being_sorted = '' # set page_sort_active var try: page_sort_active = request.session['page_sort_active'] del request.session['page_sort_active'] except KeyError: page_sort_active = '' # Check if no collections on current page no_collections = True if collections.count() == 0 else False # set this page as the last page visited request.session['last_page'] = page.name # paramaters for use with the 'delete_modal' template bm_delete_modal = { "form_name": "delete-bookmark-form", "object_type": "bookmark", "text": "the bookmark will be permanently deleted.", } page_delete_modal = { "form_name": "delete-page-form", "object_type": "page", "text": "you will lose all collections and bookmarks \ contained within.", } collection_delete_modal = { "form_name": "delete-collection-form", "object_type": "collection", "text": "you will lose all bookmarks contained \ within.", } context = { "column_width": 100 / num_of_columns, "num_of_columns": num_of_columns, "bm_data": bm_data, "page": page.name, "all_page_names": all_pages, "add_new_page_form": add_new_page_form, "edit_page_form": edit_page_form, "no_collections": no_collections, "collection_being_sorted": collection_being_sorted, "page_sort_active": page_sort_active, "bm_delete_modal": bm_delete_modal, "page_delete_modal": page_delete_modal, "collection_delete_modal": collection_delete_modal, } context = is_premium(request.user, context) return render(request, 'links/links.html', context)
def profile(request): """ The current users profile page """ user = User.objects.get(email=request.user.email) if "email-btn" in request.POST: password_change_form = UpdatedPasswordChangeForm(request.user) update_email_form = UpdateUserEmailForm(request.POST, instance=request.user) if update_email_form.is_valid(): update_email_form.save() messages.success( request, f"Your email address has been updated. Thank you.") return redirect(reverse("profile")) else: messages.error( request, f"There was an error with your form - \ please try again.") elif "pw-btn" in request.POST: update_email_form = UpdateUserEmailForm() password_change_form = UpdatedPasswordChangeForm(user=request.user, data=request.POST) if password_change_form.is_valid(): password_change_form.save() update_session_auth_hash(request, password_change_form.user) messages.success(request, f"Your password has been updated. Thank you.") return redirect(reverse("profile")) else: messages.error( request, f"There was an error with your form - \ please try again.") else: update_email_form = UpdateUserEmailForm() password_change_form = UpdatedPasswordChangeForm(request.user) # set page value for default page choice for 'add bookmark' button page = set_page_name(request) # stats num_bookmarks = Bookmark.objects.filter( user__username=request.user, ).count() num_collections = Collection.objects.filter( user__username=request.user, ).count() num_pages = Page.objects.filter(user__username=request.user, ).count() context = { "profile": user, "update_email_form": update_email_form, "password_change_form": password_change_form, "page": page, "num_bookmarks": num_bookmarks, "num_collections": num_collections, "num_pages": num_pages, } context = is_premium(request.user, context) return render(request, 'accounts/profile.html', context)