From 6c11d210e881776dee3a9f600b6def00a41e37ea Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Tue, 28 Jun 2022 23:55:44 -0700 Subject: [PATCH] Add floating window for new threads New threads get a floating window just like new replies have. This only pops up on the board detail view. Signed-off-by: Alek Ratzloff --- board/forms.py | 6 +-- board/static/board/post.js | 47 ++++++++++++++--- board/templates/board/board_detail.html | 28 ++++------ board/templates/board/post_create_view.html | 34 ++++++++++++ board/templates/board/post_detail.html | 9 +--- board/templates/board/post_success.html | 26 +++++---- board/urls.py | 1 + board/views.py | 58 ++++++++++++++++----- 8 files changed, 151 insertions(+), 58 deletions(-) create mode 100644 board/templates/board/post_create_view.html diff --git a/board/forms.py b/board/forms.py index 0cf3b56..2f5312f 100644 --- a/board/forms.py +++ b/board/forms.py @@ -22,8 +22,9 @@ class PostForm(ModelForm): model = Post fields = ["subject", "name", "text", "image"] - def __init__(self, *args, board, ip, **kwargs): + def __init__(self, *args, user, board, ip, **kwargs): super(PostForm, self).__init__(*args, **kwargs) + self.user = user self.instance.board = board self.instance.ip = ip @@ -42,10 +43,9 @@ class ReplyForm(PostForm): model = Post fields = ["name", "text", "bump", "capcode", "image"] - def __init__(self, *args, user, op, **kwargs): + def __init__(self, *args, op, **kwargs): super(ReplyForm, self).__init__(*args, **kwargs) self.instance.op = op - self.user = user def clean(self): super().clean() diff --git a/board/static/board/post.js b/board/static/board/post.js index 220288d..7ec269e 100644 --- a/board/static/board/post.js +++ b/board/static/board/post.js @@ -1,6 +1,7 @@ const OPEN = "open"; const CLOSED = "closed"; const replyWindowName = "reply-window"; +const postWindowName = "post-window"; function documentClick(e) { let sender = e.target; @@ -59,7 +60,7 @@ function openReplyWindow(replyUrl) { if (window.top.jsFrame.containsWindowName(replyWindowName)) { // if there's already a new reply window, don't override it and just let // it continue to exist. - return; + return getReplyWindow(); } let replyWindow = window.top.jsFrame.create({ @@ -70,6 +71,7 @@ function openReplyWindow(replyUrl) { url: replyUrl }); replyWindow.show(); + return replyWindow; } function getReplyWindow() { @@ -77,18 +79,49 @@ function getReplyWindow() { } function replyTextbox() { - return $("iframe").contents().find("#id_text"); + replyWindow = getReplyWindow(); + if (!replyWindow) { + return null; + } + + return replyWindow.$("#id_text") } function replyAppend(toAdd) { + let replyWindow = getReplyWindow(); let textbox = replyTextbox(); - if (textbox.length === 0) { + if (!textbox) { + $(replyWindow.iframe, "#id_text").on("load", (e) => { + replyAppend(toAdd); + }) + } else { + let caret = textbox.selectionStart; + textbox = $(textbox); + let text = textbox.val(); + textbox.val(text.substring(0, caret) + toAdd + text.substring(caret)); + textbox.focus(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Reply window +//////////////////////////////////////////////////////////////////////////////// +function openPostWindow(postUrl) { + if (window.top.jsFrame.containsWindowName(postWindowName)) { return; } - let caret = textbox[0].selectionStart; - let text = textbox.val(); - textbox.val(text.substring(0, caret) + toAdd + text.substring(caret)); - textbox.focus(); + let postWindow = window.top.jsFrame.create({ + title: "New Thread", + name: postWindowName, + width: 385, + height: 350, + url: postUrl, + }); + postWindow.show(); +} + +function getPostWindow() { + return window.top.jsFrame.getWindowByName(postWindowName); } //////////////////////////////////////////////////////////////////////////////// diff --git a/board/templates/board/board_detail.html b/board/templates/board/board_detail.html index 92c8571..06e67da 100644 --- a/board/templates/board/board_detail.html +++ b/board/templates/board/board_detail.html @@ -23,23 +23,9 @@
 
-

{% translate "Create a new thread" %}

-
-
-
- {% csrf_token %} - - {{ form.as_table }} - - - - - -
  - {% translate "Max image size" %}: - {{ max_upload_size|measure_bytes }} -
 
-
+

+ {% translate "Create a new thread" %} +

 
@@ -85,4 +71,12 @@ {% endwith %} {% endif %} + + {% endblock content %} \ No newline at end of file diff --git a/board/templates/board/post_create_view.html b/board/templates/board/post_create_view.html new file mode 100644 index 0000000..a85e2aa --- /dev/null +++ b/board/templates/board/post_create_view.html @@ -0,0 +1,34 @@ +{% extends "board/base.html" %} +{% load i18n post_body %} + +{% block content %} +
+ {% csrf_token %} + + {% for field in form %} + {% if field.name != "capcode" %} + + + + + {% endif %} + {% endfor %} + {% if capcodes %} + + + + + {% endif %} + + + + + +
{{field.label_tag}}{{field}}
{{form.capcode.label_tag}} + {{form.capcode}} +
  + {% translate "Max image size" %}: + {{ max_upload_size|measure_bytes }} +
 
+
+{% endblock content %} \ No newline at end of file diff --git a/board/templates/board/post_detail.html b/board/templates/board/post_detail.html index 464ca3b..8888547 100644 --- a/board/templates/board/post_detail.html +++ b/board/templates/board/post_detail.html @@ -54,14 +54,7 @@ $("#create_reply").on("click", (e) => { $(window).on("quote", (e, postId) => { openReplyWindow(REPLY_URL); let toAdd = ">>" + postId + "\n"; - let textbox = replyTextbox(); - if (typeof textbox === "undefined" || textbox.length === 0) { - $("iframe").on("load", () => { - replyAppend(toAdd); - }); - } else { - replyAppend(toAdd); - } + replyAppend(toAdd); }); {% endblock content %} \ No newline at end of file diff --git a/board/templates/board/post_success.html b/board/templates/board/post_success.html index 2bbdf91..75c96c7 100644 --- a/board/templates/board/post_success.html +++ b/board/templates/board/post_success.html @@ -15,16 +15,22 @@ function isIframe() { } } -setTimeout(function() { - if(isIframe()) { - // check for possible windows - let replyWindow = getReplyWindow(); - if(replyWindow) { - replyWindow.closeFrame(); +$(window).on("load", () => { + setTimeout(function() { + let params = new URLSearchParams(window.location.search); + let next = params.get("next"); + let target = isIframe() + ? window.top + : window; + if(next) { + target.location = next; + if(next.includes("#")) { + target.location.reload(); + } + } else { + target.close(); } - } else { - window.close(); - } -}, 1000 * {{window_timeout}}); + }, 1000 * {{window_timeout}}); +}); {% endblock content %} \ No newline at end of file diff --git a/board/urls.py b/board/urls.py index 847dc4e..4ccec93 100644 --- a/board/urls.py +++ b/board/urls.py @@ -10,6 +10,7 @@ urlpatterns = [ path("/", BoardView.as_view(), name="board_detail"), path("/page//", BoardView.as_view(), name="board_detail"), path("/post//", PostView.as_view(), name="post_detail"), + path("/post/create/", PostCreateView.as_view(), name="post_create"), path("/reply//", ReplyCreateView.as_view(), name="reply_create"), path("post/success/", PostSuccessView.as_view(), name="post_success"), # Reports diff --git a/board/views.py b/board/views.py index 74f09e5..d57417a 100644 --- a/board/views.py +++ b/board/views.py @@ -2,9 +2,9 @@ from typing import Any, Dict from django.conf import settings from django.contrib.auth import get_user_model, get_user from django.contrib.auth.mixins import PermissionRequiredMixin -from django.core.exceptions import ImproperlyConfigured from django.db.models import Q from django.http import Http404, HttpResponseRedirect +from django.http.request import QueryDict from django.shortcuts import get_object_or_404 from django.views.generic.base import TemplateView from django.views.generic import edit @@ -22,6 +22,7 @@ __all__ = ( "BanSuccessView", "BannedView", "BoardView", + "PostCreateView", "PostView", "PostSuccessView", "ReplyCreateView", @@ -77,9 +78,8 @@ class CreateView(edit.CreateView): return super(CreateView, self).dispatch(request, *args, **kwargs) -class BoardView(CreateView): - model = Post - form_class = PostForm +class BoardView(TemplateView): + model = Board slug_field = "url" slug_url_kwarg = "url" template_name = "board/board_detail.html" @@ -92,6 +92,10 @@ class BoardView(CreateView): ) return super(BoardView, self).get(request, *args, **kwargs) + def dispatch(self, request, *args, **kwargs): + self.board = get_object_or_404(Board, url=kwargs["url"]) + return super(BoardView, self).dispatch(request, *args, **kwargs) + def get_context_data(self, **kwargs): page = self.kwargs["page"] @@ -114,6 +118,33 @@ class BoardView(CreateView): return super(BoardView, self).get_context_data(**kwargs) +class PostCreateView(CreateView): + model = Post + form_class = PostForm + slug_field = "url" + slug_url_kwarg = "url" + template_name = "board/post_create_view.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["board"] = self.board + context["max_upload_size"] = settings.MAX_UPLOAD_SIZE + context["capcodes"] = get_objects_for_user( + get_user(self.request), "board.use_capcode" + ) + return context + + def get_form_kwargs(self): + kwargs = super(PostCreateView, self).get_form_kwargs() + kwargs["user"] = self.request.user + return kwargs + + def get_success_url(self) -> str: + query = QueryDict(mutable=True) + query["next"] = self.get_form().instance.get_absolute_url() + return reverse("board:post_success") + "?" + query.urlencode() + + class ReplyCreateView(CreateView): model = Post form_class = ReplyForm @@ -141,10 +172,14 @@ class ReplyCreateView(CreateView): kwargs["user"] = self.request.user return kwargs + def get_success_url(self) -> str: + query = QueryDict(mutable=True) + query["next"] = self.get_form().instance.get_absolute_url() + return reverse("board:post_success") + "?" + query.urlencode() -class PostView(CreateView): + +class PostView(TemplateView): model = Post - form_class = ReplyForm slug_field = "url" slug_url_kwarg = "url" @@ -158,13 +193,10 @@ class PostView(CreateView): return super(PostView, self).get_context_data(**kwargs) - def get_form_kwargs(self): - kwargs = super(PostView, self).get_form_kwargs() - post_id = self.kwargs["id"] - post = get_object_or_404(Post, id=post_id) - kwargs["op"] = post - kwargs["user"] = self.request.user - return kwargs + def dispatch(self, request, *args, **kwargs): + # Set the board on this object + self.board = get_object_or_404(Board, url=kwargs["url"]) + return super(PostView, self).dispatch(request, *args, **kwargs) class PostSuccessView(TemplateView):