add bookmarks page

This commit is contained in:
Zhao-Linux 2022-11-18 04:21:32 +07:00
parent 8108967959
commit 6e72c08ef4
9 changed files with 143 additions and 9 deletions

View file

@ -404,6 +404,7 @@ urlpatterns = [
), ),
url(r"^user$", user.UserAboutPage.as_view(), name="user_page"), url(r"^user$", user.UserAboutPage.as_view(), name="user_page"),
url(r"^edit/profile/$", user.edit_profile, name="user_edit_profile"), url(r"^edit/profile/$", user.edit_profile, name="user_edit_profile"),
url(r"^user/bookmarks", user.UserBookMarkPage.as_view(), name="user_bookmark"),
url( url(
r"^user/(?P<user>\w+)", r"^user/(?P<user>\w+)",
include( include(

View file

@ -1,8 +1,12 @@
from django.db import models from django.db import models
from django.db.models import CASCADE from django.db.models import CASCADE
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ObjectDoesNotExist
from judge.models import Profile 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"] __all__ = ["BookMark"]
@ -21,12 +25,28 @@ class BookMark(models.Model):
else: else:
return False 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: class Meta:
verbose_name = _("bookmark") verbose_name = _("bookmark")
verbose_name_plural = _("bookmarks") verbose_name_plural = _("bookmarks")
def __str__(self): def __str__(self):
return f"bookmark for {self.page}" return self.page
class MakeBookMark(models.Model): class MakeBookMark(models.Model):
bookmark = models.ForeignKey(BookMark, related_name="bookmark", on_delete=CASCADE) bookmark = models.ForeignKey(BookMark, related_name="bookmark", on_delete=CASCADE)

View file

@ -129,7 +129,7 @@ class PostList(FeedView, PageVoteListView, BookMarkListView):
.order_by() .order_by()
} }
context = self.add_pagevote_context_data(context) context = self.add_pagevote_context_data(context)
context = self.add_bookmark_context_data(context)
return context return context
def get_comment_page(self, post): def get_comment_page(self, post):

View file

@ -76,10 +76,8 @@ class BookMarkDetailView(TemplateResponseMixin, SingleObjectMixin, View):
return context return context
class BookMarkListView(ListView): class BookMarkListView(ListView):
def add_bookmark_context_data(self, context, obj_list="object_list"):
def get_context_data(self, **kwargs): for item in context[obj_list]:
context = super(BookMarkListView, self).get_context_data(**kwargs)
for item in context["object_list"]:
bookmark, _ = BookMark.objects.get_or_create( bookmark, _ = BookMark.objects.get_or_create(
page=self.get_comment_page(item) page=self.get_comment_page(item)
) )

View file

@ -72,6 +72,7 @@ from judge.views.problem import ProblemList
from judge.views.contests import ContestList from judge.views.contests import ContestList
from judge.views.submission import AllSubmissions, SubmissionsListBase from judge.views.submission import AllSubmissions, SubmissionsListBase
from judge.views.pagevote import PageVoteListView from judge.views.pagevote import PageVoteListView
from judge.views.bookmark import BookMarkListView
__all__ = [ __all__ = [
"OrganizationList", "OrganizationList",
@ -266,7 +267,7 @@ class OrganizationList(TitleMixin, ListView, OrganizationBase):
return context return context
class OrganizationHome(OrganizationDetailView, PageVoteListView): class OrganizationHome(OrganizationDetailView, PageVoteListView, BookMarkListView):
template_name = "organization/home.html" template_name = "organization/home.html"
pagevote_object_name = "posts" pagevote_object_name = "posts"
@ -294,6 +295,7 @@ class OrganizationHome(OrganizationDetailView, PageVoteListView):
context["title"] = self.object.name context["title"] = self.object.name
context["posts"], context["page_obj"] = self.get_posts_and_page_obj() context["posts"], context["page_obj"] = self.get_posts_and_page_obj()
context = self.add_pagevote_context_data(context, "posts") 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 # Hack: This allows page_obj to have page_range for non-ListView class
setattr( setattr(

View file

@ -13,6 +13,7 @@ from django.db import transaction
from django.db.models import Count, Max, Min from django.db.models import Count, Max, Min
from django.db.models.fields import DateField from django.db.models.fields import DateField
from django.db.models.functions import Cast, ExtractYear from django.db.models.functions import Cast, ExtractYear
from judge.models.bookmark import MakeBookMark
from django.forms import Form from django.forms import Form
from django.http import ( from django.http import (
Http404, Http404,
@ -52,7 +53,7 @@ from judge.utils.views import (
) )
from .contests import ContestRanking from .contests import ContestRanking
__all__ = ["UserPage", "UserAboutPage", "UserProblemsPage", "users", "edit_profile"] __all__ = ["UserPage", "UserAboutPage", "UserProblemsPage", "UserBookMarkPage", "users", "edit_profile"]
def remap_keys(iterable, mapping): def remap_keys(iterable, mapping):
@ -349,6 +350,27 @@ class UserProblemsPage(UserPage):
return context 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): class UserPerformancePointsAjax(UserProblemsPage):
template_name = "user/pp-table-body.html" template_name = "user/pp-table-body.html"

View file

@ -30,7 +30,7 @@
onclick="javascript:bookmark({{ bookmark.id }})" onclick="javascript:bookmark({{ bookmark.id }})"
> >
<i class="fa fa-bookmark-o" style="font-size: large;"></i> <i class="fa fa-bookmark-o" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Bookmark")}} {{ bookmark.id }} </span> <span class="actionbar-text">{{_("Bookmark")}}</span>
</span> </span>
</span> </span>
<span class="actionbar-block"> <span class="actionbar-block">

View file

@ -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 %}
<div class="bookmark-group">
<h3 class="unselectable toggle closed">
<span class="fa fa-chevron-right fa-fw"></span>{{ _('Bookmarked Posts') }} ({{ postlist|length }})
</h3>
<table style="display: none" class="table toggled">
<thead>
<tr>
<th>{{ _('Post') }}</th>
</tr>
</thead>
<tbody>
{% for post in postlist %}
<tr>
<td class="bookmark-name">
<a href="{{ url('blog_post', post.bookmark.page_object().id, post.bookmark.page_object().slug) }}">{{ post.bookmark.page_object().title}} </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<i>{{ _('You have not yet bookmarked any post.') }}</i>
{% endif %}
<hr>
{% if hasproblem %}
<div class="bookmark-group">
<h3 class="unselectable toggle closed">
<span class="fa fa-chevron-right fa-fw"></span>{{ _('Bookmarked Problems') }} ({{ problemlist|length }})
</h3>
<table style="display: none" class="table toggled">
<thead>
<tr>
<th>{{ _('Problem') }}</th>
</tr>
</thead>
<tbody>
{% for problem in problemlist %}
<tr>
<td class="bookmark-name">
<a href="{{ url('problem_detail', problem.bookmark.page_object().code) }}">{{ problem.bookmark.page_object().name}} </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<i>{{ _('You have not yet bookmarked any problem.') }}</i>
{% endif %}
<hr>
{% if hascontest %}
<div class="bookmark-group">
<h3 class="unselectable toggle closed">
<span class="fa fa-chevron-right fa-fw"></span>{{ _('Bookmarked Contests') }} ({{ contestlist|length }})
</h3>
<table style="display: none" class="table toggled">
<thead>
<tr>
<th>{{ _('Contest') }}</th>
</tr>
</thead>
<tbody>
{% for contest in contestlist %}
<tr>
<td class="bookmark-name">
<a href="{{ url('contest_view', contest.bookmark.page_object().key) }}">{{ contest.bookmark.page_object().name}} </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<i>{{ _('You have not yet bookmarked any contest.') }}</i>
{% endif %}
<hr>
{% endblock %}

View file

@ -7,6 +7,7 @@
{{ make_tab('impersonate', 'fa-eye', url('impersonate-start', user.user.id), _('Impersonate')) }} {{ make_tab('impersonate', 'fa-eye', url('impersonate-start', user.user.id), _('Impersonate')) }}
{% endif %} {% endif %}
{% if user.user == request.user %} {% 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')) }} {{ make_tab('edit', 'fa-edit', url('user_edit_profile'), _('Edit profile')) }}
{% else %} {% else %}
{% if perms.auth.change_user %} {% if perms.auth.change_user %}