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 <alekratz@gmail.com>
This commit is contained in:
@@ -22,8 +22,9 @@ class PostForm(ModelForm):
|
|||||||
model = Post
|
model = Post
|
||||||
fields = ["subject", "name", "text", "image"]
|
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)
|
super(PostForm, self).__init__(*args, **kwargs)
|
||||||
|
self.user = user
|
||||||
self.instance.board = board
|
self.instance.board = board
|
||||||
self.instance.ip = ip
|
self.instance.ip = ip
|
||||||
|
|
||||||
@@ -42,10 +43,9 @@ class ReplyForm(PostForm):
|
|||||||
model = Post
|
model = Post
|
||||||
fields = ["name", "text", "bump", "capcode", "image"]
|
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)
|
super(ReplyForm, self).__init__(*args, **kwargs)
|
||||||
self.instance.op = op
|
self.instance.op = op
|
||||||
self.user = user
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const OPEN = "open";
|
const OPEN = "open";
|
||||||
const CLOSED = "closed";
|
const CLOSED = "closed";
|
||||||
const replyWindowName = "reply-window";
|
const replyWindowName = "reply-window";
|
||||||
|
const postWindowName = "post-window";
|
||||||
|
|
||||||
function documentClick(e) {
|
function documentClick(e) {
|
||||||
let sender = e.target;
|
let sender = e.target;
|
||||||
@@ -59,7 +60,7 @@ function openReplyWindow(replyUrl) {
|
|||||||
if (window.top.jsFrame.containsWindowName(replyWindowName)) {
|
if (window.top.jsFrame.containsWindowName(replyWindowName)) {
|
||||||
// if there's already a new reply window, don't override it and just let
|
// if there's already a new reply window, don't override it and just let
|
||||||
// it continue to exist.
|
// it continue to exist.
|
||||||
return;
|
return getReplyWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
let replyWindow = window.top.jsFrame.create({
|
let replyWindow = window.top.jsFrame.create({
|
||||||
@@ -70,6 +71,7 @@ function openReplyWindow(replyUrl) {
|
|||||||
url: replyUrl
|
url: replyUrl
|
||||||
});
|
});
|
||||||
replyWindow.show();
|
replyWindow.show();
|
||||||
|
return replyWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReplyWindow() {
|
function getReplyWindow() {
|
||||||
@@ -77,19 +79,50 @@ function getReplyWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function replyTextbox() {
|
function replyTextbox() {
|
||||||
return $("iframe").contents().find("#id_text");
|
replyWindow = getReplyWindow();
|
||||||
|
if (!replyWindow) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replyWindow.$("#id_text")
|
||||||
}
|
}
|
||||||
|
|
||||||
function replyAppend(toAdd) {
|
function replyAppend(toAdd) {
|
||||||
|
let replyWindow = getReplyWindow();
|
||||||
let textbox = replyTextbox();
|
let textbox = replyTextbox();
|
||||||
if (textbox.length === 0) {
|
if (!textbox) {
|
||||||
return;
|
$(replyWindow.iframe, "#id_text").on("load", (e) => {
|
||||||
}
|
replyAppend(toAdd);
|
||||||
let caret = textbox[0].selectionStart;
|
})
|
||||||
|
} else {
|
||||||
|
let caret = textbox.selectionStart;
|
||||||
|
textbox = $(textbox);
|
||||||
let text = textbox.val();
|
let text = textbox.val();
|
||||||
textbox.val(text.substring(0, caret) + toAdd + text.substring(caret));
|
textbox.val(text.substring(0, caret) + toAdd + text.substring(caret));
|
||||||
textbox.focus();
|
textbox.focus();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Reply window
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
function openPostWindow(postUrl) {
|
||||||
|
if (window.top.jsFrame.containsWindowName(postWindowName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Events
|
// Events
|
||||||
|
|||||||
@@ -23,23 +23,9 @@
|
|||||||
<div class="column"> </div>
|
<div class="column"> </div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h2>{% translate "Create a new thread" %}</h2>
|
<h2>
|
||||||
</div>
|
<a id="create_post" href="{% url 'board:post_create' url=board.url %}">{% translate "Create a new thread" %}</a>
|
||||||
<div class="row">
|
</h2>
|
||||||
<form method="post" action="{% url 'board:board_detail' url=board.url %}" enctype="multipart/form-data">
|
|
||||||
{% csrf_token %}
|
|
||||||
<table>
|
|
||||||
{{ form.as_table }}
|
|
||||||
<tr>
|
|
||||||
<th> </th>
|
|
||||||
<td>
|
|
||||||
{% translate "Max image size" %}:
|
|
||||||
{{ max_upload_size|measure_bytes }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr><th> </th><td><input type="submit" value="Submit" /></td></tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column"> </div>
|
<div class="column"> </div>
|
||||||
@@ -85,4 +71,12 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const POST_URL = "{% url 'board:post_create' url=board.url %}";
|
||||||
|
$("#create_post").on("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openPostWindow(POST_URL);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
34
board/templates/board/post_create_view.html
Normal file
34
board/templates/board/post_create_view.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends "board/base.html" %}
|
||||||
|
{% load i18n post_body %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post" action="{% url 'board:post_create' url=board.url %}" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{% for field in form %}
|
||||||
|
{% if field.name != "capcode" %}
|
||||||
|
<tr>
|
||||||
|
<th>{{field.label_tag}}</th>
|
||||||
|
<td>{{field}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if capcodes %}
|
||||||
|
<tr>
|
||||||
|
<th>{{form.capcode.label_tag}}</th>
|
||||||
|
<td>
|
||||||
|
{{form.capcode}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<td>
|
||||||
|
{% translate "Max image size" %}:
|
||||||
|
{{ max_upload_size|measure_bytes }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr><td> </td><td><input type="submit" value="Submit" /></td></tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
@@ -54,14 +54,7 @@ $("#create_reply").on("click", (e) => {
|
|||||||
$(window).on("quote", (e, postId) => {
|
$(window).on("quote", (e, postId) => {
|
||||||
openReplyWindow(REPLY_URL);
|
openReplyWindow(REPLY_URL);
|
||||||
let toAdd = ">>" + postId + "\n";
|
let toAdd = ">>" + postId + "\n";
|
||||||
let textbox = replyTextbox();
|
|
||||||
if (typeof textbox === "undefined" || textbox.length === 0) {
|
|
||||||
$("iframe").on("load", () => {
|
|
||||||
replyAppend(toAdd);
|
replyAppend(toAdd);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
replyAppend(toAdd);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
@@ -15,16 +15,22 @@ function isIframe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(window).on("load", () => {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
if(isIframe()) {
|
let params = new URLSearchParams(window.location.search);
|
||||||
// check for possible windows
|
let next = params.get("next");
|
||||||
let replyWindow = getReplyWindow();
|
let target = isIframe()
|
||||||
if(replyWindow) {
|
? window.top
|
||||||
replyWindow.closeFrame();
|
: window;
|
||||||
|
if(next) {
|
||||||
|
target.location = next;
|
||||||
|
if(next.includes("#")) {
|
||||||
|
target.location.reload();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window.close();
|
target.close();
|
||||||
}
|
}
|
||||||
}, 1000 * {{window_timeout}});
|
}, 1000 * {{window_timeout}});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
@@ -10,6 +10,7 @@ urlpatterns = [
|
|||||||
path("<slug:url>/", BoardView.as_view(), name="board_detail"),
|
path("<slug:url>/", BoardView.as_view(), name="board_detail"),
|
||||||
path("<slug:url>/page/<int:page>/", BoardView.as_view(), name="board_detail"),
|
path("<slug:url>/page/<int:page>/", BoardView.as_view(), name="board_detail"),
|
||||||
path("<slug:url>/post/<int:id>/", PostView.as_view(), name="post_detail"),
|
path("<slug:url>/post/<int:id>/", PostView.as_view(), name="post_detail"),
|
||||||
|
path("<slug:url>/post/create/", PostCreateView.as_view(), name="post_create"),
|
||||||
path("<slug:url>/reply/<int:id>/", ReplyCreateView.as_view(), name="reply_create"),
|
path("<slug:url>/reply/<int:id>/", ReplyCreateView.as_view(), name="reply_create"),
|
||||||
path("post/success/", PostSuccessView.as_view(), name="post_success"),
|
path("post/success/", PostSuccessView.as_view(), name="post_success"),
|
||||||
# Reports
|
# Reports
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import Any, Dict
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model, get_user
|
from django.contrib.auth import get_user_model, get_user
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
|
from django.http.request import QueryDict
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic import edit
|
from django.views.generic import edit
|
||||||
@@ -22,6 +22,7 @@ __all__ = (
|
|||||||
"BanSuccessView",
|
"BanSuccessView",
|
||||||
"BannedView",
|
"BannedView",
|
||||||
"BoardView",
|
"BoardView",
|
||||||
|
"PostCreateView",
|
||||||
"PostView",
|
"PostView",
|
||||||
"PostSuccessView",
|
"PostSuccessView",
|
||||||
"ReplyCreateView",
|
"ReplyCreateView",
|
||||||
@@ -77,9 +78,8 @@ class CreateView(edit.CreateView):
|
|||||||
return super(CreateView, self).dispatch(request, *args, **kwargs)
|
return super(CreateView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BoardView(CreateView):
|
class BoardView(TemplateView):
|
||||||
model = Post
|
model = Board
|
||||||
form_class = PostForm
|
|
||||||
slug_field = "url"
|
slug_field = "url"
|
||||||
slug_url_kwarg = "url"
|
slug_url_kwarg = "url"
|
||||||
template_name = "board/board_detail.html"
|
template_name = "board/board_detail.html"
|
||||||
@@ -92,6 +92,10 @@ class BoardView(CreateView):
|
|||||||
)
|
)
|
||||||
return super(BoardView, self).get(request, *args, **kwargs)
|
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):
|
def get_context_data(self, **kwargs):
|
||||||
page = self.kwargs["page"]
|
page = self.kwargs["page"]
|
||||||
|
|
||||||
@@ -114,6 +118,33 @@ class BoardView(CreateView):
|
|||||||
return super(BoardView, self).get_context_data(**kwargs)
|
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):
|
class ReplyCreateView(CreateView):
|
||||||
model = Post
|
model = Post
|
||||||
form_class = ReplyForm
|
form_class = ReplyForm
|
||||||
@@ -141,10 +172,14 @@ class ReplyCreateView(CreateView):
|
|||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
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
|
model = Post
|
||||||
form_class = ReplyForm
|
|
||||||
slug_field = "url"
|
slug_field = "url"
|
||||||
slug_url_kwarg = "url"
|
slug_url_kwarg = "url"
|
||||||
|
|
||||||
@@ -158,13 +193,10 @@ class PostView(CreateView):
|
|||||||
|
|
||||||
return super(PostView, self).get_context_data(**kwargs)
|
return super(PostView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
kwargs = super(PostView, self).get_form_kwargs()
|
# Set the board on this object
|
||||||
post_id = self.kwargs["id"]
|
self.board = get_object_or_404(Board, url=kwargs["url"])
|
||||||
post = get_object_or_404(Post, id=post_id)
|
return super(PostView, self).dispatch(request, *args, **kwargs)
|
||||||
kwargs["op"] = post
|
|
||||||
kwargs["user"] = self.request.user
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
class PostSuccessView(TemplateView):
|
class PostSuccessView(TemplateView):
|
||||||
|
|||||||
Reference in New Issue
Block a user