diff --git a/dmoj/urls.py b/dmoj/urls.py index 4f0441c..9103a6a 100644 --- a/dmoj/urls.py +++ b/dmoj/urls.py @@ -404,6 +404,7 @@ urlpatterns = [ ), url(r"^user$", user.UserAboutPage.as_view(), name="user_page"), url(r"^edit/profile/$", user.edit_profile, name="user_edit_profile"), + url(r"^user/bookmarks", user.UserBookMarkPage.as_view(), name="user_bookmark"), url( r"^user/(?P\w+)", include( diff --git a/judge/models/bookmark.py b/judge/models/bookmark.py index 5df0fb9..326f3ac 100644 --- a/judge/models/bookmark.py +++ b/judge/models/bookmark.py @@ -1,8 +1,12 @@ from django.db import models from django.db.models import CASCADE from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ObjectDoesNotExist from judge.models import Profile +from judge.models.contest import Contest +from judge.models.interface import BlogPost +from judge.models.problem import Problem, Solution __all__ = ["BookMark"] @@ -21,12 +25,28 @@ class BookMark(models.Model): else: return False + def page_object(self): + try: + page = self.page + if page.startswith("p:"): + return Problem.objects.get(code=page[2:]) + elif page.startswith("c:"): + return Contest.objects.get(key=page[2:]) + elif page.startswith("b:"): + return BlogPost.objects.get(id=page[2:]) + elif page.startswith("s:"): + return Solution.objects.get(problem__code=page[2:]) + return None + except ObjectDoesNotExist: + return None + + class Meta: verbose_name = _("bookmark") verbose_name_plural = _("bookmarks") def __str__(self): - return f"bookmark for {self.page}" + return self.page class MakeBookMark(models.Model): bookmark = models.ForeignKey(BookMark, related_name="bookmark", on_delete=CASCADE) diff --git a/judge/views/blog.py b/judge/views/blog.py index a853f27..2bcc0a6 100644 --- a/judge/views/blog.py +++ b/judge/views/blog.py @@ -129,7 +129,7 @@ class PostList(FeedView, PageVoteListView, BookMarkListView): .order_by() } context = self.add_pagevote_context_data(context) - + context = self.add_bookmark_context_data(context) return context def get_comment_page(self, post): diff --git a/judge/views/bookmark.py b/judge/views/bookmark.py index e8282ae..a804089 100644 --- a/judge/views/bookmark.py +++ b/judge/views/bookmark.py @@ -76,10 +76,8 @@ class BookMarkDetailView(TemplateResponseMixin, SingleObjectMixin, View): return context class BookMarkListView(ListView): - - def get_context_data(self, **kwargs): - context = super(BookMarkListView, self).get_context_data(**kwargs) - for item in context["object_list"]: + def add_bookmark_context_data(self, context, obj_list="object_list"): + for item in context[obj_list]: bookmark, _ = BookMark.objects.get_or_create( page=self.get_comment_page(item) ) diff --git a/judge/views/organization.py b/judge/views/organization.py index 486bf77..fd2e2fa 100644 --- a/judge/views/organization.py +++ b/judge/views/organization.py @@ -72,6 +72,7 @@ from judge.views.problem import ProblemList from judge.views.contests import ContestList from judge.views.submission import AllSubmissions, SubmissionsListBase from judge.views.pagevote import PageVoteListView +from judge.views.bookmark import BookMarkListView __all__ = [ "OrganizationList", @@ -266,7 +267,7 @@ class OrganizationList(TitleMixin, ListView, OrganizationBase): return context -class OrganizationHome(OrganizationDetailView, PageVoteListView): +class OrganizationHome(OrganizationDetailView, PageVoteListView, BookMarkListView): template_name = "organization/home.html" pagevote_object_name = "posts" @@ -294,6 +295,7 @@ class OrganizationHome(OrganizationDetailView, PageVoteListView): context["title"] = self.object.name context["posts"], context["page_obj"] = self.get_posts_and_page_obj() context = self.add_pagevote_context_data(context, "posts") + context = self.add_bookmark_context_data(context, "posts") # Hack: This allows page_obj to have page_range for non-ListView class setattr( diff --git a/judge/views/user.py b/judge/views/user.py index da4120a..bf49269 100644 --- a/judge/views/user.py +++ b/judge/views/user.py @@ -13,6 +13,7 @@ from django.db import transaction from django.db.models import Count, Max, Min from django.db.models.fields import DateField from django.db.models.functions import Cast, ExtractYear +from judge.models.bookmark import MakeBookMark from django.forms import Form from django.http import ( Http404, @@ -52,7 +53,7 @@ from judge.utils.views import ( ) from .contests import ContestRanking -__all__ = ["UserPage", "UserAboutPage", "UserProblemsPage", "users", "edit_profile"] +__all__ = ["UserPage", "UserAboutPage", "UserProblemsPage", "UserBookMarkPage", "users", "edit_profile"] def remap_keys(iterable, mapping): @@ -349,6 +350,27 @@ class UserProblemsPage(UserPage): return context +class UserBookMarkPage(UserPage): + template_name = "user/user-bookmarks.html" + + def get_context_data(self, **kwargs): + context = super(UserBookMarkPage, self).get_context_data(**kwargs) + + makedownlist = MakeBookMark.objects.filter(user=self.object) + pagelist = makedownlist.filter(bookmark__page__startswith='b') + problemlist = makedownlist.filter(bookmark__page__startswith='p') + contestlist = makedownlist.filter(bookmark__page__startswith='c') + + context["pagelist"] = makedownlist + context["postlist"] = pagelist + context["problemlist"] = problemlist + context["contestlist"] = contestlist + + context["haspost"] = pagelist.exists() + context["hasproblem"] = problemlist.exists() + context["hascontest"] = contestlist.exists() + return context + class UserPerformancePointsAjax(UserProblemsPage): template_name = "user/pp-table-body.html" diff --git a/templates/actionbar/list.html b/templates/actionbar/list.html index 1489514..da0c078 100644 --- a/templates/actionbar/list.html +++ b/templates/actionbar/list.html @@ -30,7 +30,7 @@ onclick="javascript:bookmark({{ bookmark.id }})" > - {{_("Bookmark")}} {{ bookmark.id }} + {{_("Bookmark")}} diff --git a/templates/user/user-bookmarks.html b/templates/user/user-bookmarks.html new file mode 100644 index 0000000..39ea196 --- /dev/null +++ b/templates/user/user-bookmarks.html @@ -0,0 +1,90 @@ +{% extends "user/user-base.html" %} + +{% block title_ruler %}{% endblock %} + +{% block title_row %} + {% set tab = 'bookmark' %} + {% include "user/user-tabs.html" %} +{% endblock %} + +{% block user_content %} + {% if haspost %} +
+

+ {{ _('Bookmarked Posts') }} ({{ postlist|length }}) +

+ + + + + + + + {% for post in postlist %} + + + + {% endfor %} + + +
+ {% else %} + {{ _('You have not yet bookmarked any post.') }} + {% endif %} +
+ {% if hasproblem %} +
+

+ {{ _('Bookmarked Problems') }} ({{ problemlist|length }}) +

+ + + + + + + + {% for problem in problemlist %} + + + + {% endfor %} + + +
+ {% else %} + {{ _('You have not yet bookmarked any problem.') }} + {% endif %} +
+ {% if hascontest %} +
+

+ {{ _('Bookmarked Contests') }} ({{ contestlist|length }}) +

+ + + + + + + + {% for contest in contestlist %} + + + + {% endfor %} + + +
+ {% else %} + {{ _('You have not yet bookmarked any contest.') }} + {% endif %} +
+ +{% endblock %} diff --git a/templates/user/user-tabs.html b/templates/user/user-tabs.html index 1fab2e6..096a45b 100644 --- a/templates/user/user-tabs.html +++ b/templates/user/user-tabs.html @@ -7,6 +7,7 @@ {{ make_tab('impersonate', 'fa-eye', url('impersonate-start', user.user.id), _('Impersonate')) }} {% endif %} {% if user.user == request.user %} + {{ make_tab('bookmark', 'fa-bookmark', url('user_bookmark'), _('Bookmark')) }} {{ make_tab('edit', 'fa-edit', url('user_edit_profile'), _('Edit profile')) }} {% else %} {% if perms.auth.change_user %}