This commit is contained in:
anhkha2003 2023-10-06 03:45:49 -05:00
commit 509d1ba2f9
22 changed files with 328 additions and 222 deletions

View file

@ -485,6 +485,9 @@ META_REMOTE_ADDRESS_KEY = "REMOTE_ADDR"
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# Chunk upload
CHUNK_UPLOAD_DIR = "/tmp/chunk_upload_tmp"
try:
with open(os.path.join(os.path.dirname(__file__), "local_settings.py")) as f:
exec(f.read(), globals())

View file

@ -44,6 +44,7 @@ from judge.views import (
language,
license,
mailgun,
markdown_editor,
notification,
organization,
preview,
@ -405,6 +406,11 @@ urlpatterns = [
]
),
),
url(
r"^markdown_editor/",
markdown_editor.MarkdownEditor.as_view(),
name="markdown_editor",
),
url(
r"^submission_source_file/(?P<filename>(\w|\.)+)",
submission.SubmissionSourceFileView.as_view(),

View file

@ -168,7 +168,7 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
)
def _get_queryset(self, target_comment):
if target_comment != None:
if target_comment:
queryset = target_comment.get_descendants(include_self=True)
queryset = (
queryset.select_related("author__user")
@ -217,11 +217,11 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
context["has_comments"] = queryset.exists()
context["comment_lock"] = self.is_comment_locked()
context["comment_list"] = queryset
context["comment_list"] = list(queryset)
context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD
if queryset.exists():
context["comment_root_id"] = queryset[0].id
context["comment_root_id"] = context["comment_list"][0].id
else:
context["comment_root_id"] = 0
context["comment_parent_none"] = 1
@ -234,4 +234,5 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
context["limit"] = DEFAULT_OFFSET
context["comment_count"] = comment_count
context["profile"] = self.request.profile
return context

View file

@ -35,7 +35,7 @@ def save_upload(f, path):
# pass callback function to post_upload
def handle_upload(f, fileattrs, upload_dir, post_upload=None):
chunks_dir = os.path.join(tempfile.gettempdir(), "chunk_upload_tmp")
chunks_dir = settings.CHUNK_UPLOAD_DIR
if not os.path.exists(os.path.dirname(chunks_dir)):
os.makedirs(os.path.dirname(chunks_dir))
chunked = False

View file

@ -15,12 +15,11 @@ from django.http import (
HttpResponseBadRequest,
HttpResponseForbidden,
)
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, render
from django.utils.translation import gettext as _
from django.views.decorators.http import require_POST
from django.views.generic import DetailView, UpdateView
from django.urls import reverse_lazy
from django.template import loader
from reversion import revisions
from reversion.models import Version
@ -42,11 +41,6 @@ __all__ = [
@login_required
# def get_more_reply(request, id):
# queryset = Comment.get_pk(id)
def vote_comment(request, delta):
if abs(delta) != 1:
return HttpResponseBadRequest(
@ -156,6 +150,7 @@ def get_comments(request, limit=10):
revisions=Count("versions", distinct=True),
)[offset : offset + limit]
)
profile = None
if request.user.is_authenticated:
profile = request.profile
queryset = queryset.annotate(
@ -164,10 +159,11 @@ def get_comments(request, limit=10):
new_offset = offset + min(len(queryset), limit)
comment_html = loader.render_to_string(
return render(
request,
"comments/content-list.html",
{
"request": request,
"profile": profile,
"comment_root_id": comment_root_id,
"comment_list": queryset,
"vote_hide_threshold": settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD,
@ -181,8 +177,6 @@ def get_comments(request, limit=10):
},
)
return HttpResponse(comment_html)
def get_show_more(request):
return get_comments(request)

View file

@ -0,0 +1,14 @@
from django.views import View
from django.shortcuts import render
from django.utils.translation import gettext_lazy as _
class MarkdownEditor(View):
def get(self, request):
return render(
request,
"markdown_editor/markdown_editor.html",
{
"title": _("Markdown Editor"),
},
)

View file

@ -130,6 +130,18 @@ msgstr "Thể thức"
msgid "Rating"
msgstr ""
#: templates/markdown_editor/markdown_editor.html:107
msgid "Insert Image"
msgstr "Chèn hình ảnh"
#: templates/markdown_editor/markdown_editor.html:110
msgid "From the web"
msgstr "Từ web"
#: templates/markdown_editor/markdown_editor.html:116
msgid "From your computer"
msgstr "Từ máy tính của bạn"
#: judge/admin/contest.py:201
msgid "Access"
msgstr "Truy cập"
@ -6255,3 +6267,4 @@ msgstr "Chọn tất cả"
#~ msgid "Hard"
#~ msgstr "Khó"

View file

@ -39,6 +39,12 @@ msgstr "Đăng ký tên"
msgid "Report"
msgstr "Báo cáo"
msgid "Insert Image"
msgstr "Chèn hình ảnh"
msgid "Save"
msgstr "Lưu"
msgid "2sat"
msgstr ""
@ -593,3 +599,4 @@ msgstr ""
msgid "z-function"
msgstr ""

View file

@ -78,7 +78,7 @@
#chat-container {
display: flex;
width: 100%;
height: calc(100vh - 3em);
height: calc(100vh - $navbar_height);
border: 1px solid #ccc;
/*border-radius: 0 4px 0 0;*/
border-bottom: 0;
@ -220,5 +220,6 @@
@media (max-width: 799px) {
#chat-area {
height: calc(100vh - $navbar_height_mobile);
max-height: -webkit-fill-available;
}
}

View file

@ -214,7 +214,7 @@ a {
input, textarea {
min-width: 100%;
max-width: 100%;
font-size: 1em;
font-size: 15px;
}
}

View file

@ -386,6 +386,11 @@ function onWindowReady() {
});
});
$('a').click(function() {
var href = $(this).attr('href');
if (!href || href === '#' || href.startsWith("javascript")) {
return;
}
$("#loading-bar").show();
$("#loading-bar").animate({ width: "100%" }, 2000, function() {
$(this).hide().css({ width: 0});

View file

@ -1712,10 +1712,10 @@ noscript #noscript {
color: rgb(178, 171, 161);
}
#chat-icon {
color: rgb(249, 146, 97);
color: rgb(200, 196, 189);
}
#chat-icon:hover {
color: rgb(114, 255, 114);
color: rgb(249, 146, 97);
}
#nav-lang-icon {
color: rgb(51, 125, 255);
@ -2471,16 +2471,13 @@ input[type="text"], input[type="password"], input[type="email"], input[type="num
box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px inset;
}
textarea {
color: rgb(178, 172, 162);
background-image: none;
background-color: rgb(24, 26, 27);
border-color: rgb(62, 68, 70);
box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px inset;
}
textarea:hover {
border-color: rgba(16, 87, 144, 0.8);
box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px inset,
rgba(16, 91, 150, 0.6) 0px 0px 4px;
border-color: rgb(140, 130, 115);
}
input[type="text"]:hover, input[type="password"]:hover {
border-color: rgba(16, 87, 144, 0.8);
@ -2488,9 +2485,7 @@ input[type="text"]:hover, input[type="password"]:hover {
rgba(16, 91, 150, 0.6) 0px 0px 4px;
}
textarea:focus {
border-color: rgba(16, 87, 144, 0.8);
box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 1px inset,
rgba(16, 91, 150, 0.6) 0px 0px 8px; outline-color: initial;
border-color: rgb(140, 130, 115); outline-color: initial;
}
input[type="text"]:focus, input[type="password"]:focus {
border-color: rgba(16, 87, 144, 0.8);
@ -2552,7 +2547,7 @@ input[type="text"]:focus, input[type="password"]:focus {
ul.pagination a:hover {
color: rgb(232, 230, 227);
background-image: initial;
background-color: rgb(8, 128, 104);
background-color: rgb(163, 62, 18);
border-color: initial;
}
ul.pagination > li > a,
@ -2563,14 +2558,14 @@ ul.pagination > li > span {
border-color: rgb(199, 70, 8);
}
ul.pagination > .disabled-page > a {
color: rgb(157, 148, 136);
background-color: rgba(3, 66, 54, 0.5);
border-color: rgba(126, 117, 103, 0.5);
color: rgb(223, 220, 215);
background-color: rgb(137, 78, 57);
border-color: rgb(199, 68, 21);
}
ul.pagination > .disabled-page > span {
color: rgb(157, 148, 136);
background-color: rgba(3, 66, 54, 0.5);
border-color: rgba(126, 117, 103, 0.5);
color: rgb(223, 220, 215);
background-color: rgb(137, 78, 57);
border-color: rgb(199, 68, 21);
}
ul.pagination > .active-page > a {
color: rgb(232, 230, 227);
@ -2922,8 +2917,8 @@ a.voted {
color: rgb(152, 143, 129);
}
.list-contest {
box-shadow: rgba(3, 66, 54, 0.2) 0px 4px 8px,
rgba(3, 66, 54, 0.19) 0px 6px 20px;
box-shadow: rgb(49, 53, 55) 0px 1px 2px,
rgb(49, 53, 55) 0px 1px 5px;
}
#contest-calendar th {
border-bottom-color: rgb(62, 68, 70);
@ -3058,7 +3053,13 @@ a.voted {
}
#chat-input {
color: rgb(232, 230, 227);
border-color: rgb(159, 117, 19);
border-color: rgb(140, 130, 115);
}
#chat-input::-webkit-input-placeholder {
color: rgb(152, 143, 129);
}
#chat-input::placeholder {
color: rgb(152, 143, 129);
}
.selected-status-row {
background-color: rgb(49, 53, 55);
@ -3077,15 +3078,6 @@ a.voted {
#chat-info {
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 3px;
}
#refresh-button {
background-image: initial;
background-color: transparent;
border-color: initial;
}
#refresh-button:hover {
background-image: initial;
background-color: rgb(40, 111, 17);
}
.status-circle {
stroke: rgb(232, 230, 227);
}
@ -3104,11 +3096,12 @@ a.voted {
color: rgb(232, 230, 227);
}
.chat-input-icon {
color: rgb(249, 146, 97);
color: rgb(232, 230, 227);
background-color: rgb(48, 104, 78);
}
.chat-input-icon:hover {
background-image: initial;
background-color: rgb(49, 53, 55);
background-color: rgb(62, 136, 112);
}
.chat .active-span {
color: rgb(169, 162, 151);
@ -3873,64 +3866,11 @@ mjx-assistive-mml {
mjx-stretchy-v > mjx-ext {
border-color: transparent;
}
.noUi-target,
.noUi-target * {
-webkit-tap-highlight-color: transparent;
.recently-attempted ul {
list-style-image: initial;
}
.noUi-target {
background-image: initial;
background-color: rgb(27, 29, 30);
border-color: rgb(60, 65, 68);
box-shadow: rgb(32, 35, 37) 0px 1px 1px inset,
rgb(62, 68, 70) 0px 3px 6px -5px;
}
.noUi-connect {
background-image: initial;
background-color: rgb(50, 147, 140);
box-shadow: rgba(38, 42, 43, 0.45) 0px 0px 3px inset;
}
.noUi-handle {
border-color: rgb(59, 64, 66);
background-image: initial;
background-color: rgb(24, 26, 27);
box-shadow: rgb(24, 26, 27) 0px 0px 1px inset,
rgb(35, 38, 40) 0px 1px 7px inset,
rgb(62, 68, 70) 0px 3px 6px -3px;
}
.noUi-active {
box-shadow: rgb(24, 26, 27) 0px 0px 1px inset,
rgb(43, 47, 49) 0px 1px 7px inset,
rgb(62, 68, 70) 0px 3px 6px -3px;
}
.noUi-handle::after,
.noUi-handle::before {
background-image: initial;
background-color: rgb(38, 41, 42);
}
[disabled] .noUi-connect {
background-image: initial;
background-color: rgb(64, 69, 72);
}
.noUi-pips {
color: rgb(168, 160, 149);
}
.noUi-value-sub {
color: rgb(200, 195, 188);
}
.noUi-marker {
background-image: initial;
background-color: rgb(53, 57, 59);
}
.noUi-marker-large,
.noUi-marker-sub {
background-image: initial;
background-color: rgb(72, 78, 81);
}
.noUi-tooltip {
border-color: rgb(59, 64, 66);
background-image: initial;
background-color: rgb(24, 26, 27);
color: rgb(232, 230, 227);
.organization-row:last-child {
border-bottom-color: initial;
}
/* Override Style */

View file

@ -13,7 +13,7 @@ div.dmmd-preview-update {
}
div.dmmd-preview-content {
padding: 0 7px;
padding: 0 8px;
}
div.dmmd-preview.dmmd-preview-has-content div.dmmd-preview-update {
@ -21,7 +21,8 @@ div.dmmd-preview.dmmd-preview-has-content div.dmmd-preview-update {
}
div.dmmd-preview-has-content div.dmmd-preview-content {
padding-bottom: 7px;
padding-bottom: 8px;
padding-top: 8px;
}
div.dmmd-no-button div.dmmd-preview-update {

View file

@ -14,7 +14,7 @@
width: 100%;
background: #fff;
border: 1px solid DarkGray;
font-family: Consolas, "Liberation Mono", Monaco, "Courier New", monospace !important;
font-family: "Noto Sans",Arial,"Lucida Grande",sans-serif !important;
}
.wmd-preview {

View file

@ -14,7 +14,7 @@
width: 100%;
background: #fff;
border: 1px solid DarkGray;
font-family: Consolas, "Liberation Mono", Monaco, "Courier New", monospace !important;
font-family: "Noto Sans",Arial,"Lucida Grande",sans-serif !important;
}
.wmd-preview {

View file

@ -161,8 +161,7 @@ input {
}
textarea {
padding: 4px 8px;
color: #555;
padding: 8px;
background: #FFF none;
border: 1px solid $border_gray;
border-radius: $widget_border_radius;
@ -172,8 +171,7 @@ textarea {
}
textarea:hover {
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 4px rgba(82, 168, 236, 0.6);
border-color: black;
}
input {
@ -184,8 +182,8 @@ input {
}
textarea:focus {
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
border-color: black;
border-width: unset;
outline: 0;
}
@ -322,7 +320,7 @@ input {
// Bootstrap-y pagination
ul.pagination a:hover {
color: #FFF;
background: #0aa082;
background: #cc4e17;
border: none;
}
@ -338,22 +336,6 @@ ul.pagination {
li {
display: inline;
// &:first-child > {
// a, span {
// margin-left: 0;
// border-top-left-radius: $widget_border_radius;
// border-bottom-left-radius: $widget_border_radius;
// }
// }
// &:last-child > {
// a, span {
// margin-left: 0;
// border-top-right-radius: $widget_border_radius;
// border-bottom-right-radius: $widget_border_radius;
// }
// }
> {
a, span {
position: relative;
@ -373,15 +355,15 @@ ul.pagination {
.disabled-page > {
a {
color: #888;
background-color: #04534380;
border-color: #04534380;
color: #f1efef;
background-color: #ab6247;
border-color: #6a240b;
}
span {
color: #888;
background-color: #04534380;
border-color: #04534380;
color: #f1efef;
background-color: #ab6247;
border-color: #6a240b;
}
}

View file

@ -195,8 +195,8 @@
#chat-input-container {
padding-left: 3%;
}
#chat-area {
padding-bottom: 1.5em;
.back-button {
display: none;
}
.back-button {
display: none;

View file

@ -1,13 +1,10 @@
{% set logged_in = request.user.is_authenticated %}
{% set profile = request.profile if logged_in else None %}
{% for node in mptt_tree(comment_list) recursive %}
<li id="comment-{{ node.id }}" data-revision="{{ node.revisions - 1 }}" data-max-revision="{{ node.revisions - 1 }}"
data-revision-ajax="{{ url('comment_revision_ajax', node.id) }}" class="comment">
<div class="comment-display{% if node.score <= vote_hide_threshold %} bad-comment{% endif %}">
<div class="info">
<div class="vote">
{% if logged_in %}
{% if profile %}
<a href="javascript:comment_upvote({{ node.id }})"
class="upvote-link fa fa-chevron-up fa-fw{% if node.vote_score == 1 %} voted{% endif %}"></a>
{% else %}
@ -16,7 +13,7 @@
{% endif %}
<br>
<div class="comment-score">{{ node.score }}</div>
{% if logged_in %}
{% if profile %}
<a href="javascript:comment_downvote({{ node.id }})"
class="downvote-link fa fa-chevron-down fa-fw{% if node.vote_score == -1 %} voted{% endif %}"></a>
{% else %}
@ -55,7 +52,7 @@
<a href="?comment-id={{node.id}}#comment-{{ node.id }}" title="{{ _('Link') }}" class="comment-link">
<i class="fa fa-link fa-fw"></i>
</a>
{% if logged_in and not comment_lock %}
{% if profile and not comment_lock %}
{% set can_edit = node.author.id == profile.id and not profile.mute %}
{% if can_edit %}
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}"

View file

@ -3,7 +3,7 @@
<h2 id="comment-header">
<i style="padding-right: 0.3em" class="fa fa-comments"></i>{{ _('Comments') }}
{% if can_comment %}
<a href="" id="write-comment" style="float: right; font-size: 0.6em; margin-right: -26px;"> {{ _('Write comment') }} </a>
<a href="#" id="write-comment" style="float: right; font-size: 0.6em; margin-right: -26px;"> {{ _('Write comment') }} </a>
{% endif %}
</h2>
{% if can_comment %}

View file

@ -30,7 +30,7 @@
{% endif %}
<script type="text/javascript">
$(document).ready(function () {
let loading_gif = "<img src=\"{{static('loading.gif')}}\" style=\"height: 1.5em; margin-bottom: 3px\" class=\"loading\">";
let loading_gif = "<img src=\"{{static('loading.gif')}}\" style=\"height: 3em; margin-bottom: 3px\" class=\"loading\">";
window.reply_comment = function (parent) {
var $comment_reply = $('#comment-' + parent + '-reply');
var reply_id = 'reply-' + parent;
@ -186,6 +186,7 @@
var $comment = $("#comment-" + id + "-children");
$comment.append(data);
}
MathJax.typeset($('#comments')[0]);
}
})
}

View file

@ -112,9 +112,8 @@
{% endblock %}
{% macro contest_head(contest) %}
{% spaceless %}
<a href="{{ url('contest_view', contest.key) }}" class="contest-list-title" style="margin-right: 5px;">
{{- contest.name -}}
{{contest.name}}
</a>
<br>
<div class="contest-tags" style="margin-top: 5px;">
@ -161,7 +160,6 @@
</span>
{% endfor %}
</div>
{% endspaceless %}
{% endmacro %}
{% macro time_left(contest, padding_top = true) %}

View file

@ -0,0 +1,143 @@
{% extends "base.html" %}
{% block media %}
<style>
main{
overflow: hidden;
}
#content{
width: 100%;
}
#content.wrapper{
padding: 0;
}
.form-area{
float: left;
width: 47%;
height: 100%
}
.wmd-preview{
float: right;
margin-top: 0;
}
.width-controller{
width: 51%;
}
.wmd-input{
height: calc(100vh - 72px);
}
.right-markdown{
height: calc(100vh - 72px);
overflow-y: scroll;
}
.wrap{
display: flex;
}
</style>
{% endblock %}
{% block js_media %}
<script>
$(document).ready(function(){
$("#wmd-input-id_body").on("keyup", function() {
const csrfToken = "{{ csrf_token }}";
$.ajax({
url: "{{url('blog_preview')}}",
type: 'POST',
headers: {
'X-CSRFToken': csrfToken, // Include the CSRF token in the headers
},
data: {
preview: $(this).val()
},
success: function(data) {
$('#display').html(data);
MathJax.typeset();
},
error: function(error) {
alert(error);
console.log(error.message)
}
})
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const leftDiv = document.getElementById("wmd-input-id_body");
const rightDiv = document.getElementById("display");
leftDiv.addEventListener("scroll", function() {
rightDiv.scrollTop = leftDiv.scrollTop;
});
rightDiv.addEventListener("scroll", function() {
leftDiv.scrollTop = rightDiv.scrollTop;
});
});
</script>
<script src="{{ static('pagedown/Markdown.Converter.js') }}"></script>
<script src="{{ static('pagedown-extra/pagedown/Markdown.Converter.js') }}"></script>
<script src="{{ static('pagedown/Markdown.Sanitizer.js') }}"></script>
<script src="{{ static('pagedown/Markdown.Editor.js') }}"></script>
<script src="{{ static('pagedown-extra/Markdown.Extra.js') }}"></script>
<script src="{{ static('pagedown_init.js') }}"></script>
<script src="{{ static('mathjax3_config.js') }}"></script>
<script src="http://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script src="{{ static('pagedown_math.js') }}"></script>
{% endblock %}
{% block title_row %}
{% endblock %}
{% block title_ruler %}
{% endblock %}
{% block body %}
<div class="wrap">
<div id="new-comment" class="form-area">
<input type="hidden" name="parent" id="id_parent">
<div class="comment-post-wrapper">
<div id="comment-form-body"><div class="wmd-wrapper image-upload-enabled">
<div class="wmd-panel">
<div id="wmd-button-bar-id_body"></div>
<textarea id="wmd-input-id_body" class="wmd-input" name="body" required=""></textarea>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="wmd-panel wmd-preview dmmd-preview dmmd-no-button">
<div class="dmmd-preview-update"><i class="fa fa-refresh"></i> {{_('Update Preview')}}</div>
<div class="dmmd-preview-content content-description"></div>
</div>
<div class="pagedown-image-upload">
<h2>{{_('Insert Image')}}</h2>
<div class="form-row">
<div>
<label class="label">{{_('From the web')}}</label>
<input class="url-input" type="text" placeholder="http://">
</div>
</div>
<div class="form-row">
<div>
<label class="label">{{_('From your computer')}}</label>
<input class="file-input" type="file" name="image" id="file" data-action="/pagedown/image-upload/" accept="image/*">
</div>
</div>
<div class="submit-row">
<div class="submit-loading"></div>
<input class="submit-input show" type="submit" value="{{_('Save')}}" name="_addanother">
<p class="deletelink-box"><a href="#" class="close-image-upload deletelink">{{_('Cancel')}}</a></p>
</div>
</div>
</div></div>
</div>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="width-controller wmd-panel wmd-preview dmmd-preview dmmd-no-button dmmd-preview-has-content">
<div class="right-markdown dmmd-preview-content content-description" id="display"></div>
</div>
</div>
{% endblock %}