Add post modify view
This allows moderators to modify posts (add sticky, etc). Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -115,3 +115,17 @@ class BanForm(ModelForm):
|
|||||||
else:
|
else:
|
||||||
expires = None
|
expires = None
|
||||||
self.instance.expires = expires
|
self.instance.expires = expires
|
||||||
|
|
||||||
|
|
||||||
|
class PostModifyForm(ModelForm):
|
||||||
|
"""
|
||||||
|
A form used to modify the attributes of a post (sticky, locked, sink, etc)
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Post
|
||||||
|
fields = ["bump", "sticky"]
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
super(PostModifyForm, self).clean()
|
||||||
|
print(self.fields["sticky"])
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class Board(models.Model):
|
|||||||
return self.max_pages * self.threads_per_page
|
return self.max_pages * self.threads_per_page
|
||||||
|
|
||||||
def prune_threads(self):
|
def prune_threads(self):
|
||||||
to_remove = self.threads.order_by("-last_bump")[self.max_threads :]
|
to_remove = self.threads.order_by("-sticky", "-last_bump")[self.max_threads :]
|
||||||
for thread in to_remove:
|
for thread in to_remove:
|
||||||
thread.delete()
|
thread.delete()
|
||||||
|
|
||||||
@@ -93,6 +93,8 @@ class Post(models.Model):
|
|||||||
ip = models.GenericIPAddressField()
|
ip = models.GenericIPAddressField()
|
||||||
# Capcode
|
# Capcode
|
||||||
capcode = models.ForeignKey("Capcode", null=True, blank=True, on_delete=SET_NULL)
|
capcode = models.ForeignKey("Capcode", null=True, blank=True, on_delete=SET_NULL)
|
||||||
|
# Post is stickied
|
||||||
|
sticky = models.BooleanField(default=False, blank=True)
|
||||||
# Creation time
|
# Creation time
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
# Last bump time
|
# Last bump time
|
||||||
@@ -116,6 +118,9 @@ class Post(models.Model):
|
|||||||
image_width = models.IntegerField(null=True)
|
image_width = models.IntegerField(null=True)
|
||||||
image_height = models.IntegerField(null=True)
|
image_height = models.IntegerField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = [("set_sticky", "Can sticky post")]
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.image:
|
if self.image:
|
||||||
self.original_image_name = Path(self.image.name).parts[-1]
|
self.original_image_name = Path(self.image.name).parts[-1]
|
||||||
|
|||||||
@@ -4,6 +4,18 @@ if (typeof window.banWindowName === "undefined") {
|
|||||||
window.banWindowName = "ban-window";
|
window.banWindowName = "ban-window";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof window.menuItemFactories !== "undefined") {
|
||||||
|
window.menuItemFactories.push(
|
||||||
|
(postElement) => $("<a>")
|
||||||
|
.text("Ban")
|
||||||
|
.attr("href", "#")
|
||||||
|
.on("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openBanWindow($(postElement).attr("data-ban-url"));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getBanWindow() {
|
function getBanWindow() {
|
||||||
return window.top.jsFrame.getWindowByName(banWindowName);
|
return window.top.jsFrame.getWindowByName(banWindowName);
|
||||||
}
|
}
|
||||||
@@ -20,4 +32,4 @@ function openBanWindow(banUrl) {
|
|||||||
url: banUrl,
|
url: banUrl,
|
||||||
});
|
});
|
||||||
banWindow.show();
|
banWindow.show();
|
||||||
}
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
if (typeof window.menuItemFactories !== "undefined") {
|
|
||||||
window.menuItemFactories.push(
|
|
||||||
(postElement) => $("<a>")
|
|
||||||
.text("Ban")
|
|
||||||
.attr("href", "#")
|
|
||||||
.on("click", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
openBanWindow($(postElement).attr("data-ban-url"));
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
36
board/static/board/modify.js
Normal file
36
board/static/board/modify.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
if (typeof window.menuItemFactories !== "undefined") {
|
||||||
|
window.menuItemFactories.push(
|
||||||
|
(postElement) => $("<a>")
|
||||||
|
.text("Modify post")
|
||||||
|
.attr("href", "#")
|
||||||
|
.on("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openModifyWindow($(postElement).attr("data-modify-url"));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: this should be a const, but it will cause an error if included twice in
|
||||||
|
// the same page (like an iframe).
|
||||||
|
if (typeof window.modifyWindowName === "undefined") {
|
||||||
|
window.modifyWindowName = "modify-window";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModifyWindow() {
|
||||||
|
return window.top.jsFrame.getWindowByName(modifyWindowName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openModifyWindow(modifyUrl) {
|
||||||
|
if (window.top.jsFrame.containsWindowName(modifyWindowName)) {
|
||||||
|
getModifyWindow().closeFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
let modifyWindow = window.top.jsFrame.create({
|
||||||
|
title: "Modifying post",
|
||||||
|
name: modifyWindowName,
|
||||||
|
width: 475,
|
||||||
|
height: 475,
|
||||||
|
url: modifyUrl,
|
||||||
|
});
|
||||||
|
modifyWindow.show();
|
||||||
|
}
|
||||||
@@ -85,6 +85,10 @@ th {
|
|||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post_sticky {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.post_id {
|
.post_id {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
{{block.super}}
|
{{block.super}}
|
||||||
<script src="{% static 'board/jquery.js' %}"></script>
|
<script src="{% static 'board/jquery.js' %}"></script>
|
||||||
<script src="{% static 'board/jsframe.min.js' %}"></script>
|
<script src="{% static 'board/jsframe.min.js' %}"></script>
|
||||||
<script src="{% static 'board/ban_window.js' %}"></script>
|
<script src="{% static 'board/ban.js' %}"></script>
|
||||||
{% endblock extrahead %}
|
{% endblock extrahead %}
|
||||||
|
|
||||||
{% block footer %}
|
{% block footer %}
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
{% load i18n static %}
|
{% load i18n static %}
|
||||||
{# Title #}
|
{# Title #}
|
||||||
{% block title %}{% translate "Ban success" %}{% endblock %}
|
{% block title %}{% translate "Ban success" %}{% endblock %}
|
||||||
{# Extra JS #}
|
|
||||||
{% block extrajs %}
|
|
||||||
<script src="{% static 'board/ban_window.js' %}"></script>
|
|
||||||
{% endblock extrajs %}
|
|
||||||
{# Body #}
|
{# Body #}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row" id="message">
|
<div class="row" id="message">
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<title>{% block title %}{% if title %}{{title}}{% else %}Index{% endif %}{% endblock %}</title>
|
<title>{% block title %}{% if title %}{{title}}{% else %}Index{% endif %}{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="{% static 'board/style.css' %}">
|
<link rel="stylesheet" href="{% static 'board/style.css' %}">
|
||||||
|
<link rel="stylesheet" href="{% static 'board/font-awesome/css/font-awesome.min.css' %}">
|
||||||
{% block extrastyle %}{% endblock %}
|
{% block extrastyle %}{% endblock %}
|
||||||
<script src="{% static 'board/jquery.js' %}"></script>
|
<script src="{% static 'board/jquery.js' %}"></script>
|
||||||
<script src="{% static 'board/jsframe.min.js' %}"></script>
|
<script src="{% static 'board/jsframe.min.js' %}"></script>
|
||||||
<script src="{% static 'board/post.js' %}"></script>
|
<script src="{% static 'board/post.js' %}"></script>
|
||||||
{% if perms.board.create_ban %}
|
{% if perms.board.create_ban %}
|
||||||
<script src="{% static 'board/ban_window.js' %}"></script>
|
<script src="{% static 'board/ban_window.js' %}"></script>
|
||||||
<script src="{% static 'board/ban_menu.js' %}"></script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block extrajs %}{% endblock %}
|
{% block extrajs %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
17
board/templates/board/post_modify_view.html
Normal file
17
board/templates/board/post_modify_view.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{% extends "board/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post" action="{% url 'board:post_modify' post.id %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{% if perms.board.can_sticky %}
|
||||||
|
<tr>
|
||||||
|
<th>{{form.sticky.label_tag}}</th>
|
||||||
|
<td>{{form.sticky}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr><td> </td><td><input type="submit" value="Modify post" /></td></tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
{% if perms.board.create_ban %}
|
{% if perms.board.create_ban %}
|
||||||
data-ban-url="{% url 'board:ban_create' board.url post.id %}"
|
data-ban-url="{% url 'board:ban_create' board.url post.id %}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if perms.board.can_sticky %}
|
||||||
|
data-modify-url="{% url 'board:post_modify' post.id %}"
|
||||||
|
{% endif %}
|
||||||
>
|
>
|
||||||
{# Image #}
|
{# Image #}
|
||||||
{% if post.thumbnail %}
|
{% if post.thumbnail %}
|
||||||
@@ -24,7 +27,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Post ID, username, time #}
|
{# Post ID, sticky, username, time #}
|
||||||
|
{% if post.sticky and not post.op %}
|
||||||
|
<span title="Stickied" class="fa fa-sticky-note"></span>
|
||||||
|
{% endif %}
|
||||||
<a href="#p{{post.id}}">#.</a>
|
<a href="#p{{post.id}}">#.</a>
|
||||||
<span class="post_id">{{post.id}}</span>
|
<span class="post_id">{{post.id}}</span>
|
||||||
{% if post.subject %}
|
{% if post.subject %}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ urlpatterns = [
|
|||||||
path("ban/<slug:url>/<int:id>/", BanCreateView.as_view(), name="ban_create"),
|
path("ban/<slug:url>/<int:id>/", BanCreateView.as_view(), name="ban_create"),
|
||||||
path("ban/success/", BanSuccessView.as_view(), name="ban_success"),
|
path("ban/success/", BanSuccessView.as_view(), name="ban_success"),
|
||||||
path("banned", BannedView.as_view(), name="banned"),
|
path("banned", BannedView.as_view(), name="banned"),
|
||||||
|
# Other moderation pages
|
||||||
|
path("modify/<int:pk>/", PostModifyView.as_view(), name="post_modify"),
|
||||||
]
|
]
|
||||||
# TODO - make this conditional so we can serve images up with whatever server we want
|
# TODO - make this conditional so we can serve images up with whatever server we want
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from django.utils import timezone
|
|||||||
|
|
||||||
from guardian.shortcuts import get_objects_for_user
|
from guardian.shortcuts import get_objects_for_user
|
||||||
|
|
||||||
from board.forms import BanForm, PostForm, ReplyForm, ReportForm
|
from board.forms import *
|
||||||
from board.models import Ban, BanTemplate, Board, Post, Report
|
from board.models import Ban, BanTemplate, Board, Post, Report
|
||||||
from board.utils import *
|
from board.utils import *
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ __all__ = (
|
|||||||
"BannedView",
|
"BannedView",
|
||||||
"BoardView",
|
"BoardView",
|
||||||
"PostCreateView",
|
"PostCreateView",
|
||||||
|
"PostModifyView",
|
||||||
"PostView",
|
"PostView",
|
||||||
"PostSuccessView",
|
"PostSuccessView",
|
||||||
"ReplyCreateView",
|
"ReplyCreateView",
|
||||||
@@ -109,7 +110,9 @@ class BoardView(TemplateView):
|
|||||||
last_page = (thread_count // threads_per_page) + 1
|
last_page = (thread_count // threads_per_page) + 1
|
||||||
|
|
||||||
kwargs["board"] = self.board
|
kwargs["board"] = self.board
|
||||||
kwargs["threads"] = self.board.threads.order_by("-last_bump")[start:end]
|
kwargs["threads"] = self.board.threads.order_by("-sticky", "-last_bump")[
|
||||||
|
start:end
|
||||||
|
]
|
||||||
kwargs["current_page"] = page
|
kwargs["current_page"] = page
|
||||||
kwargs["pages"] = range(1, last_page + 1)
|
kwargs["pages"] = range(1, last_page + 1)
|
||||||
kwargs["last_page"] = last_page
|
kwargs["last_page"] = last_page
|
||||||
@@ -145,6 +148,24 @@ class PostCreateView(CreateView):
|
|||||||
return reverse("board:post_success") + "?" + query.urlencode()
|
return reverse("board:post_success") + "?" + query.urlencode()
|
||||||
|
|
||||||
|
|
||||||
|
class PostModifyView(PermissionRequiredMixin, edit.UpdateView):
|
||||||
|
model = Post
|
||||||
|
form_class = PostModifyForm
|
||||||
|
template_name = "board/post_modify_view.html"
|
||||||
|
|
||||||
|
def has_permission(self) -> bool:
|
||||||
|
user = self.request.user
|
||||||
|
if not user:
|
||||||
|
return False
|
||||||
|
# TODO add more permissions as required
|
||||||
|
return user.has_perm("board.can_sticky")
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
self.post_obj = get_object_or_404(Post, id=kwargs["pk"])
|
||||||
|
self.board = self.post_obj.board
|
||||||
|
return super(PostModifyView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ReplyCreateView(CreateView):
|
class ReplyCreateView(CreateView):
|
||||||
model = Post
|
model = Post
|
||||||
form_class = ReplyForm
|
form_class = ReplyForm
|
||||||
|
|||||||
Reference in New Issue
Block a user