From e686c3b23536d9a65b525be0a8419e22aa71a135 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Sun, 17 Jul 2022 15:08:33 -0700 Subject: [PATCH] Add ActionSuccessView ActionSuccessView is a a generic view that indicates that something was successful, e.g. deleting a post or banning a user. This hopefully reduces the amount of boilerplate code used for creating success pages since most of them can derive from this generic view. The report and delete success views are updated to use this directly. The ban and modify success views are updated to derive from this class, with special permissions required. The post success view is updated to derive from this class, using a different template. Signed-off-by: Alek Ratzloff --- board/static/board/ban.js | 3 + board/static/board/modify.js | 1 + board/static/board/post.js | 9 ++- board/templates/board/action_success.html | 23 ++++++++ .../templates/board/post_delete_success.html | 33 ----------- board/templates/board/report_success.html | 33 ----------- board/urls.py | 26 +++++++-- board/views.py | 56 +++++++------------ threadchat/settings.py | 6 +- 9 files changed, 78 insertions(+), 112 deletions(-) create mode 100644 board/templates/board/action_success.html delete mode 100644 board/templates/board/post_delete_success.html delete mode 100644 board/templates/board/report_success.html diff --git a/board/static/board/ban.js b/board/static/board/ban.js index 6be66fc..8cd516e 100644 --- a/board/static/board/ban.js +++ b/board/static/board/ban.js @@ -39,5 +39,8 @@ function openBanWindow(banUrl) { window.innerHeight / 2, "RIGHT_CENTER" ); + $(banWindow.iframe, "iframe").on("load", () => { + banWindow.iframe.contentWindow.thisWindow = banWindow; + }); banWindow.show(); } diff --git a/board/static/board/modify.js b/board/static/board/modify.js index 9947a3b..8d3246c 100644 --- a/board/static/board/modify.js +++ b/board/static/board/modify.js @@ -34,6 +34,7 @@ function openModifyWindow(modifyUrl) { $(modifyWindow.iframe, "iframe").on("load", () => { fitWindowToContent(modifyWindow); modifyWindow.setResizable(false); + modifyWindow.iframe.contentWindow.thisWindow = modifyWindow; }); modifyWindow.show(); } \ No newline at end of file diff --git a/board/static/board/post.js b/board/static/board/post.js index 86d0702..53228cb 100644 --- a/board/static/board/post.js +++ b/board/static/board/post.js @@ -121,6 +121,7 @@ function openReplyWindow(replyUrl) { if (textarea) { textarea.focus(); } + replyWindow.iframe.contentWindow.thisWindow = replyWindow; }); replyWindow.show(); return replyWindow; @@ -171,7 +172,11 @@ function openPostWindow(postUrl) { }); $(postWindow.iframe, "iframe").on("load", () => { fitWindowToContent(postWindow); - postWindow.$("#id_text").focus(); + let textbox = postWindow.$("#id_text"); + if (textbox) { + textbox.focus(); + } + postWindow.iframe.contentWindow.thisWindow = postWindow; }); postWindow.show(); } @@ -201,6 +206,7 @@ function openReportWindow(reportUrl) { }); $(reportWindow.iframe, "iframe").on("load", () => { fitWindowToContent(reportWindow); + reportWindow.iframe.contentWindow.thisWindow = reportWindow; }); reportWindow.show(); } @@ -226,6 +232,7 @@ function openDeleteWindow(deleteUrl) { $(deleteWindow.iframe, "iframe").on("load", () => { fitWindowToContent(deleteWindow); deleteWindow.setResizable(false); + deleteWindow.iframe.contentWindow.thisWindow = deleteWindow; }); deleteWindow.show(); } diff --git a/board/templates/board/action_success.html b/board/templates/board/action_success.html new file mode 100644 index 0000000..9c950ba --- /dev/null +++ b/board/templates/board/action_success.html @@ -0,0 +1,23 @@ +{% extends "board/base.html" %} +{% load i18n static %} +{# Title #} +{% block title %}{% translate "Action success" %}{% endblock %} +{# Body #} +{% block content %} +
+ {{message}} + {# We do not use pluralize filter for "seconds" because it's a pain to get it to translate. #} + {% blocktranslate %}This window will close in {{window_timeout}} second(s).{% endblocktranslate %} +
+ + +{% endblock %} \ No newline at end of file diff --git a/board/templates/board/post_delete_success.html b/board/templates/board/post_delete_success.html deleted file mode 100644 index a6fecac..0000000 --- a/board/templates/board/post_delete_success.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "board/base.html" %} -{% load i18n static %} -{# Title #} -{% block title %}{% translate "Post delete success" %}{% endblock %} -{# Body #} -{% block content %} -
- {# We do not use pluralize filter for "seconds" because it's a pain to get it to translate. #} - {% blocktranslate %}Delete successful. This window will close in {{window_timeout}} second(s).{% endblocktranslate %} -
- - -{% endblock %} \ No newline at end of file diff --git a/board/templates/board/report_success.html b/board/templates/board/report_success.html deleted file mode 100644 index 5974af8..0000000 --- a/board/templates/board/report_success.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "board/base.html" %} -{% load i18n static %} -{# Title #} -{% block title %}{% translate "Report success" %}{% endblock %} -{# Body #} -{% block content %} -
- {# We do not use pluralize filter for "seconds" because it's a pain to get it to translate. #} - {% blocktranslate %}Post reported. This window will close in {{window_timeout}} second(s).{% endblocktranslate %} -
- - -{% endblock %} \ No newline at end of file diff --git a/board/urls.py b/board/urls.py index 10eaa88..ecf3aa7 100644 --- a/board/urls.py +++ b/board/urls.py @@ -1,6 +1,7 @@ -from django.urls import path from django.conf import settings from django.conf.urls.static import static +from django.urls import path +from django.utils.translation import gettext as _ from board.views import * @@ -17,20 +18,35 @@ urlpatterns = [ path("post/success/", PostSuccessView.as_view(), name="post_success"), # Reports path("report///", ReportView.as_view(), name="report_form"), - path("report/success/", ReportSuccessView.as_view(), name="report_success"), + path( + "report/success/", + ActionSuccessView.as_view( + window_timeout=settings.REPORT_WINDOW_CLOSE_TIMEOUT, + message=_("Post reported."), + ), + name="report_success", + ), # Bans path("ban///", BanCreateView.as_view(), name="ban_create"), - path("ban/success/", BanSuccessView.as_view(), name="ban_success"), + path( + "ban/success/", + BanSuccessView.as_view(window_timeout=settings.ACTION_SUCCESS_CLOSE_TIMEOUT), + name="ban_success", + ), path("banned/", BannedView.as_view(), name="banned"), # Other moderation pages path("modify//", PostModifyView.as_view(), name="post_modify"), path( - "modify/success/", PostModifySuccessView.as_view(), name="post_modify_success" + "modify/success/", + PostModifySuccessView.as_view( + window_timeout=settings.ACTION_SUCCESS_CLOSE_TIMEOUT + ), + name="post_modify_success", ), path("post/delete//", PostDeleteView.as_view(), name="post_delete"), path( "post/delete/success/", - PostDeleteSuccessView.as_view(), + ActionSuccessView.as_view(window_timeout=settings.ACTION_SUCCESS_CLOSE_TIMEOUT), name="post_delete_success", ), ] diff --git a/board/views.py b/board/views.py index f204fde..802764a 100644 --- a/board/views.py +++ b/board/views.py @@ -19,6 +19,7 @@ from board.models import Ban, BanTemplate, Board, NewsPost, Post, Report from board.utils import * __all__ = ( + "ActionSuccessView", "BanCreateView", "BanSuccessView", "BannedView", @@ -30,10 +31,8 @@ __all__ = ( "PostView", "PostSuccessView", "PostDeleteView", - "PostDeleteSuccessView", "ReplyCreateView", "ReportView", - "ReportSuccessView", ) @@ -48,6 +47,18 @@ def can_modify(user): ) +class ActionSuccessView(TemplateView): + template_name = "board/action_success.html" + message = "Action completed." + window_timeout = 0 + + def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: + context = super().get_context_data(**kwargs) + context["message"] = self.message + context["window_timeout"] = self.window_timeout + return context + + class BannedView(TemplateView): template_name = "board/banned.html" @@ -156,7 +167,8 @@ class PostCreateView(CreateView): def get_success_url(self) -> str: query = QueryDict(mutable=True) - query["next"] = self.get_form().instance.get_absolute_url() + query["next"] = self.get_form().instance.get_absolute_url().split("#")[0] + print(query["next"]) return reverse("board:post_success") + "?" + query.urlencode() @@ -181,8 +193,7 @@ class PostModifyView(PermissionRequiredMixin, edit.UpdateView): return kwargs -class PostModifySuccessView(PermissionRequiredMixin, TemplateView): - template_name = "board/post_modify_success.html" +class PostModifySuccessView(PermissionRequiredMixin, ActionSuccessView): raise_exception = True def has_permission(self) -> bool: @@ -190,7 +201,6 @@ class PostModifySuccessView(PermissionRequiredMixin, TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context["window_timeout"] = settings.BAN_WINDOW_CLOSE_TIMEOUT context["can_modify"] = self.has_permission() return context @@ -248,13 +258,9 @@ class PostView(TemplateView): return super(PostView, self).dispatch(request, *args, **kwargs) -class PostSuccessView(TemplateView): +class PostSuccessView(ActionSuccessView): template_name = "board/post_success.html" - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["window_timeout"] = settings.POST_WINDOW_CLOSE_TIMEOUT - return context + window_timeout = settings.POST_WINDOW_CLOSE_TIMEOUT class PostDeleteView(PermissionRequiredMixin, edit.DeleteView): @@ -282,15 +288,6 @@ class PostDeleteView(PermissionRequiredMixin, edit.DeleteView): return HttpResponseRedirect(success_url) -class PostDeleteSuccessView(TemplateView): - template_name = "board/post_delete_success.html" - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["window_timeout"] = settings.BAN_WINDOW_CLOSE_TIMEOUT - return context - - class ReportView(CreateView): model = Report form_class = ReportForm @@ -312,15 +309,6 @@ class ReportView(CreateView): return kwargs -class ReportSuccessView(TemplateView): - template_name = "board/report_success.html" - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["window_timeout"] = settings.REPORT_WINDOW_CLOSE_TIMEOUT - return context - - class BanCreateView(PermissionRequiredMixin, edit.CreateView): model = Ban form_class = BanForm @@ -364,16 +352,10 @@ class BanCreateView(PermissionRequiredMixin, edit.CreateView): return super().dispatch(request, *args, **kwargs) -class BanSuccessView(PermissionRequiredMixin, TemplateView): +class BanSuccessView(PermissionRequiredMixin, ActionSuccessView): permission_required = "ban.create" - template_name = "board/ban_success.html" raise_exception = True - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["window_timeout"] = settings.BAN_WINDOW_CLOSE_TIMEOUT - return context - class NewsListView(list.ListView): model = NewsPost diff --git a/threadchat/settings.py b/threadchat/settings.py index ef6f68e..6f1e957 100644 --- a/threadchat/settings.py +++ b/threadchat/settings.py @@ -161,13 +161,13 @@ if USE_HCAPTCHA: # How many seconds to wait before closing the report window after a report is # created. -# By default, wait 5 seconds. This should give users plenty of time to read it. -REPORT_WINDOW_CLOSE_TIMEOUT = 5 +# By default, wait 3 seconds. This should give users plenty of time to read it. +REPORT_WINDOW_CLOSE_TIMEOUT = 3 # How many seconds to wait before closing the ban window after a ban is created. # By default, wait 0 seconds and close immediately. It is assumed that the ban # is created successfully, and if an error occurs, the window won't close anyway. -BAN_WINDOW_CLOSE_TIMEOUT = 0 +ACTION_SUCCESS_CLOSE_TIMEOUT = 0 # How many seconds to wait before closing the new post window after a post is # created.