Trying out JSFrame for windows
Winbox has this annoying bug where you can't move the window below the calculated area of the document, so you can't drag it over blank space. JSFrame fixes this and does basically what we want as well. This has been implemented for post replies and I am going to implement it for reports and ban creation too. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
8
board/static/board/jsframe.min.js
vendored
Normal file
8
board/static/board/jsframe.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -16,11 +16,24 @@ function documentClick(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doQuote(e) {
|
function doQuote(e) {
|
||||||
|
$(window).trigger("quote", [$(e.target).text()]);
|
||||||
|
/*
|
||||||
|
return;
|
||||||
let idText = $("#id_text");
|
let idText = $("#id_text");
|
||||||
|
// Try to set ID text
|
||||||
|
if (!idText.length) {
|
||||||
|
idText = $("iframe").contents().find("#id_text");
|
||||||
|
}
|
||||||
|
// If we couldn't find an ID text, open the appropriate window
|
||||||
|
if (!idText.length) {
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
let caret = idText[0].selectionStart;
|
let caret = idText[0].selectionStart;
|
||||||
let text = idText.val();
|
let text = idText.val();
|
||||||
let toAdd = ">>" + e.target.innerText + "\n";
|
let toAdd = ">>" + e.target.innerText + "\n";
|
||||||
idText.val(text.substring(0, caret) + toAdd + text.substring(caret));
|
idText.val(text.substring(0, caret) + toAdd + text.substring(caret));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeMenu(e) {
|
function closeMenu(e) {
|
||||||
@@ -78,6 +91,7 @@ $(document).on("click", documentClick);
|
|||||||
$(document).on("click", ".post_id", doQuote);
|
$(document).on("click", ".post_id", doQuote);
|
||||||
$(window).on("load", () => {
|
$(window).on("load", () => {
|
||||||
window.reportWindow = null;
|
window.reportWindow = null;
|
||||||
|
window.jsFrame = new JSFrame();
|
||||||
});
|
});
|
||||||
|
|
||||||
window.menuItemFactories = [];
|
window.menuItemFactories = [];
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
{% block extrastyle %}{% endblock %}
|
{% block extrastyle %}{% endblock %}
|
||||||
<script src="{% static 'board/jquery.js' %}"></script>
|
<script src="{% static 'board/jquery.js' %}"></script>
|
||||||
<script src="{% static 'board/winbox.bundle.js' %}"></script>
|
<script src="{% static 'board/winbox.bundle.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>
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="column"> </div>
|
<div class="column"> </div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
<h2>
|
||||||
|
<a id="create_reply" href="{% url 'board:reply_create' url=board.url id=post.id %}">{% translate "Reply to this thread" %}</a>
|
||||||
|
</h2>
|
||||||
|
{% comment %}
|
||||||
<form method="post" action="{% url 'board:post_detail' url=board.url id=post.id %}" enctype="multipart/form-data">
|
<form method="post" action="{% url 'board:post_detail' url=board.url id=post.id %}" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<table>
|
<table>
|
||||||
@@ -36,6 +40,7 @@
|
|||||||
<tr><td> </td><td><input type="submit" value="Submit" /></td></tr>
|
<tr><td> </td><td><input type="submit" value="Submit" /></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
{% endcomment %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column"> </div>
|
<div class="column"> </div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,4 +56,62 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const REPLY_URL = "{% url 'board:reply_create' url=board.url id=post.id %}";
|
||||||
|
const replyWindowName = "reply-window";
|
||||||
|
|
||||||
|
function openReplyWindow() {
|
||||||
|
if(window.jsFrame.containsWindowName(replyWindowName)) {
|
||||||
|
// if there's already a new reply window, don't override it and just let
|
||||||
|
// it continue to exist.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.top.replyWindow = window.jsFrame.create({
|
||||||
|
title: "New Reply",
|
||||||
|
name: replyWindowName,
|
||||||
|
width: 385,
|
||||||
|
height: 350,
|
||||||
|
x: "center",
|
||||||
|
y: "center",
|
||||||
|
url: REPLY_URL,
|
||||||
|
});
|
||||||
|
window.top.replyWindow.show();
|
||||||
|
window.top.replyWindow.on("hid", (frame, info) => console.log("hidden"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function replyTextbox() {
|
||||||
|
return $("iframe").contents().find("#id_text");
|
||||||
|
}
|
||||||
|
|
||||||
|
function replyAppend(toAdd) {
|
||||||
|
let textbox = replyTextbox();
|
||||||
|
if(textbox.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let caret = textbox[0].selectionStart;
|
||||||
|
let text = textbox.val();
|
||||||
|
textbox.val(text.substring(0, caret) + toAdd + text.substring(caret));
|
||||||
|
textbox.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#create_reply").on("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openReplyWindow();
|
||||||
|
});
|
||||||
|
$(window).on("load", () => { window.top.replyWindow = null; });
|
||||||
|
$(window).on("quote", (e, postId) => {
|
||||||
|
openReplyWindow();
|
||||||
|
let toAdd = ">>" + postId + "\n";
|
||||||
|
let textbox = replyTextbox();
|
||||||
|
if (typeof textbox === "undefined" || textbox.length === 0) {
|
||||||
|
$("iframe").on("load", () => {
|
||||||
|
replyAppend(toAdd);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
replyAppend(toAdd);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
29
board/templates/board/post_success.html
Normal file
29
board/templates/board/post_success.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends "board/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% blocktranslate %}
|
||||||
|
Post created. Closing window in {{window_timeout}} second(s).
|
||||||
|
{% endblocktranslate %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function isIframe() {
|
||||||
|
try {
|
||||||
|
return window.self !== window.top;
|
||||||
|
} catch (_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
if(isIframe()) {
|
||||||
|
// check for possible windows
|
||||||
|
if(typeof window.top.replyWindow !== "undefined" && window.top.replyWindow) {
|
||||||
|
window.top.replyWindow.closeFrame();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
}, 1000 * {{window_timeout}});
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
||||||
19
board/templates/board/reply_create_view.html
Normal file
19
board/templates/board/reply_create_view.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends "board/base.html" %}
|
||||||
|
{% load i18n post_body %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post" action="{% url 'board:reply_create' url=board.url id=post.id %}" 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><td> </td><td><input type="submit" value="Submit" /></td></tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
@@ -10,6 +10,8 @@ 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>/reply/<int:id>/", ReplyCreateView.as_view(), name="reply_create"),
|
||||||
|
path("post/success/", PostSuccessView.as_view(), name="post_success"),
|
||||||
# Reports
|
# Reports
|
||||||
path("report/<slug:url>/<int:id>/", ReportView.as_view(), name="report_form"),
|
path("report/<slug:url>/<int:id>/", ReportView.as_view(), name="report_form"),
|
||||||
path("report/success/", ReportSuccessView.as_view(), name="report_success"),
|
path("report/success/", ReportSuccessView.as_view(), name="report_success"),
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ __all__ = (
|
|||||||
"BannedView",
|
"BannedView",
|
||||||
"BoardView",
|
"BoardView",
|
||||||
"PostView",
|
"PostView",
|
||||||
|
"PostSuccessView",
|
||||||
|
"ReplyCreateView",
|
||||||
"ReportView",
|
"ReportView",
|
||||||
"ReportSuccessView",
|
"ReportSuccessView",
|
||||||
)
|
)
|
||||||
@@ -105,6 +107,32 @@ class BoardView(CreateView):
|
|||||||
return super(BoardView, self).get_context_data(**kwargs)
|
return super(BoardView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ReplyCreateView(CreateView):
|
||||||
|
model = Post
|
||||||
|
form_class = ReplyForm
|
||||||
|
slug_field = "url"
|
||||||
|
slug_url_kwarg = "url"
|
||||||
|
template_name = "board/reply_create_view.html"
|
||||||
|
success_url = reverse_lazy("board:post_success")
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["board"] = self.board
|
||||||
|
post_id = self.kwargs["id"]
|
||||||
|
context["post"] = get_object_or_404(Post, id=post_id)
|
||||||
|
context["max_upload_size"] = settings.MAX_UPLOAD_SIZE
|
||||||
|
print(context["board"])
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
kwargs = super(ReplyCreateView, self).get_form_kwargs()
|
||||||
|
post_id = self.kwargs["id"]
|
||||||
|
post = get_object_or_404(Post, id=post_id)
|
||||||
|
kwargs["op"] = post
|
||||||
|
kwargs["reply"] = post
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class PostView(CreateView):
|
class PostView(CreateView):
|
||||||
model = Post
|
model = Post
|
||||||
form_class = ReplyForm
|
form_class = ReplyForm
|
||||||
@@ -130,6 +158,15 @@ class PostView(CreateView):
|
|||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PostSuccessView(TemplateView):
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
class ReportView(CreateView):
|
class ReportView(CreateView):
|
||||||
model = Report
|
model = Report
|
||||||
form_class = ReportForm
|
form_class = ReportForm
|
||||||
@@ -160,7 +197,7 @@ class ReportSuccessView(TemplateView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class BanCreateView(PermissionRequiredMixin, CreateView):
|
class BanCreateView(PermissionRequiredMixin, edit.CreateView):
|
||||||
model = Ban
|
model = Ban
|
||||||
form_class = BanForm
|
form_class = BanForm
|
||||||
permission_required = "ban.create"
|
permission_required = "ban.create"
|
||||||
@@ -190,7 +227,7 @@ class BanCreateView(PermissionRequiredMixin, CreateView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form_kwargs(self) -> Dict[str, Any]:
|
def get_form_kwargs(self) -> Dict[str, Any]:
|
||||||
kwargs = super(CreateView, self).get_form_kwargs()
|
kwargs = super(edit.CreateView, self).get_form_kwargs()
|
||||||
post_id = self.kwargs["id"]
|
post_id = self.kwargs["id"]
|
||||||
post = get_object_or_404(Post, id=post_id)
|
post = get_object_or_404(Post, id=post_id)
|
||||||
kwargs["op"] = post
|
kwargs["op"] = post
|
||||||
|
|||||||
@@ -160,3 +160,9 @@ REPORT_WINDOW_CLOSE_TIMEOUT = 5
|
|||||||
# By default, wait 0 seconds and close immediately. It is assumed that the ban
|
# 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.
|
# is created successfully, and if an error occurs, the window won't close anyway.
|
||||||
BAN_WINDOW_CLOSE_TIMEOUT = 0
|
BAN_WINDOW_CLOSE_TIMEOUT = 0
|
||||||
|
|
||||||
|
# How many seconds to wait before closing the new post window after a post is
|
||||||
|
# created.
|
||||||
|
# By default, wait 0 seconds. If there is an error, the window won't close
|
||||||
|
# because it will be redirected elsewhere.
|
||||||
|
POST_WINDOW_CLOSE_TIMEOUT = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user