diff --git a/judge/comments.py b/judge/comments.py index 21481394ff..618f419c0d 100644 --- a/judge/comments.py +++ b/judge/comments.py @@ -20,7 +20,7 @@ from judge.dblock import LockModel from judge.models import Comment, CommentLock -from judge.widgets import HeavyPreviewPageDownWidget +from judge.widgets import MartorWidget class CommentForm(ModelForm): @@ -31,9 +31,7 @@ class Meta: 'parent': forms.HiddenInput(), } - if HeavyPreviewPageDownWidget is not None: - widgets['body'] = HeavyPreviewPageDownWidget(preview=reverse_lazy('comment_preview'), - preview_timeout=1000, hide_preview_button=True) + widgets['body'] = MartorWidget(attrs={'data-markdownfy-url': reverse_lazy('comment_preview')}) def __init__(self, request, *args, **kwargs): self.request = request diff --git a/judge/forms.py b/judge/forms.py index 87003e56f2..cf9d842e84 100644 --- a/judge/forms.py +++ b/judge/forms.py @@ -20,7 +20,7 @@ WebAuthnCredential from judge.utils.mail import validate_email_domain from judge.utils.subscription import newsletter_id -from judge.widgets import HeavyPreviewPageDownWidget, Select2MultipleWidget, Select2Widget +from judge.widgets import MartorWidget, Select2MultipleWidget, Select2Widget TOTP_CODE_LENGTH = 6 @@ -63,11 +63,7 @@ class Meta: fields.append('math_engine') widgets['math_engine'] = Select2Widget(attrs={'style': 'width:200px'}) - if HeavyPreviewPageDownWidget is not None: - widgets['about'] = HeavyPreviewPageDownWidget( - preview=reverse_lazy('profile_preview'), - attrs={'style': 'max-width:700px;min-width:700px;width:700px'}, - ) + widgets['about'] = MartorWidget(attrs={'data-markdownfy-url': reverse_lazy('profile_preview')}) def clean_about(self): if 'about' in self.changed_data and not self.instance.has_any_solves: @@ -173,8 +169,7 @@ class Meta: model = Organization fields = ['about', 'logo_override_image', 'admins'] widgets = {'admins': Select2MultipleWidget(attrs={'style': 'width: 200px'})} - if HeavyPreviewPageDownWidget is not None: - widgets['about'] = HeavyPreviewPageDownWidget(preview=reverse_lazy('organization_preview')) + widgets['about'] = MartorWidget(attrs={'data-markdownfy-url': reverse_lazy('organization_preview')}) class CustomAuthenticationForm(AuthenticationForm): diff --git a/judge/views/comment.py b/judge/views/comment.py index 7b2e086a7e..f87e981df4 100644 --- a/judge/views/comment.py +++ b/judge/views/comment.py @@ -7,6 +7,7 @@ from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, \ HttpResponseRedirect from django.shortcuts import get_object_or_404 +from django.urls import reverse_lazy from django.utils.translation import gettext as _ from django.views.decorators.http import require_POST from django.views.generic import DetailView, UpdateView @@ -16,7 +17,7 @@ from judge.dblock import LockModel from judge.models import Comment, CommentVote from judge.utils.views import TitleMixin -from judge.widgets import MathJaxPagedownWidget +from judge.widgets import MartorWidget __all__ = ['upvote_comment', 'downvote_comment', 'CommentEditAjax', 'CommentContent', 'CommentEdit'] @@ -122,8 +123,14 @@ class CommentEditForm(ModelForm): class Meta: model = Comment fields = ['body'] - if MathJaxPagedownWidget is not None: - widgets = {'body': MathJaxPagedownWidget(attrs={'id': 'id-edit-comment-body'})} + widgets = { + 'body': MartorWidget( + attrs={ + 'id': 'id_edit', + 'data-markdownfy-url': reverse_lazy('comment_preview'), + }, + ), + } class CommentEditAjax(LoginRequiredMixin, CommentMixin, UpdateView): diff --git a/judge/views/ticket.py b/judge/views/ticket.py index eec3d45b43..3b012339a8 100644 --- a/judge/views/ticket.py +++ b/judge/views/ticket.py @@ -22,11 +22,9 @@ from judge.utils.tickets import filter_visible_tickets, own_ticket_filter from judge.utils.views import SingleObjectFormView, TitleMixin, paginate_query_context from judge.views.problem import ProblemMixin -from judge.widgets import HeavyPreviewPageDownWidget +from judge.widgets import MartorWidget -ticket_widget = (forms.Textarea() if HeavyPreviewPageDownWidget is None else - HeavyPreviewPageDownWidget(preview=reverse_lazy('ticket_preview'), - preview_timeout=1000, hide_preview_button=True)) +ticket_widget = MartorWidget(attrs={'data-markdownfy-url': reverse_lazy('ticket_preview')}) class TicketForm(forms.Form): diff --git a/judge/views/widgets.py b/judge/views/widgets.py index f1aec4ef0f..e4b234ae68 100644 --- a/judge/views/widgets.py +++ b/judge/views/widgets.py @@ -6,9 +6,9 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.core.files.storage import default_storage -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, \ + HttpResponseRedirect from django.views.decorators.http import require_POST -from martor.api import imgur_uploader from judge.models import Submission @@ -51,12 +51,11 @@ def django_uploader(image): @login_required def martor_image_uploader(request): + if not request.user.is_staff: + return HttpResponseNotFound() if request.method != 'POST' or not request.is_ajax() or 'markdown-image-upload' not in request.FILES: return HttpResponseBadRequest('Invalid request') image = request.FILES['markdown-image-upload'] - if request.user.is_staff: - data = django_uploader(image) - else: - data = imgur_uploader(image) + data = django_uploader(image) return HttpResponse(data, content_type='application/json') diff --git a/judge/widgets/martor.py b/judge/widgets/martor.py index 9f8738e0bf..e7911d0d5b 100644 --- a/judge/widgets/martor.py +++ b/judge/widgets/martor.py @@ -12,6 +12,8 @@ class Media: class AdminMartorWidget(OldAdminMartorWidget): + UPLOADS_ENABLED = True + class Media: css = MartorWidget.Media.css js = ['admin/js/jquery.init.js', 'martor-mathjax.js'] diff --git a/resources/comments.scss b/resources/comments.scss index 85290afdb7..5e7bf67dd2 100644 --- a/resources/comments.scss +++ b/resources/comments.scss @@ -60,6 +60,10 @@ a { box-sizing: border-box; } +.comment-edit-form { + min-width: 60em; +} + .comment-post-wrapper { padding-bottom: 5px; diff --git a/resources/martor-description.scss b/resources/martor-description.scss index 90d2d09dc1..410f3035ce 100644 --- a/resources/martor-description.scss +++ b/resources/martor-description.scss @@ -2,6 +2,8 @@ form .martor-preview { @include content-description; + + min-height: 400px; ul li { list-style: unset !important; @@ -21,7 +23,7 @@ form .martor-preview { } .section-martor { - div[data-tab="editor-tab-description"] { + div[data-tab^="editor-tab-"] { padding: 0; } @@ -33,6 +35,12 @@ form .martor-preview { font-size: 0.8rem; } + .martor-toolbar { + flex: 0 1 auto !important; + overflow-x: auto; + overflow-y: hidden; + } + .martor-field { height: 400px; } diff --git a/resources/misc.scss b/resources/misc.scss index c80fe4a8d3..ea3afb4015 100644 --- a/resources/misc.scss +++ b/resources/misc.scss @@ -35,7 +35,7 @@ } .centered-form { - max-width: 700px; + max-width: 800px; margin: auto; .submit-bar { diff --git a/resources/ticket.scss b/resources/ticket.scss index 255322ee01..98041152c7 100644 --- a/resources/ticket.scss +++ b/resources/ticket.scss @@ -3,7 +3,7 @@ form#ticket-form { display: block; margin: 0 auto; - max-width: 750px; + max-width: 800px; padding-top: 1em; #id_title { @@ -72,7 +72,7 @@ div.ticket-title { display: flex; flex-direction: row; flex-wrap: wrap-reverse; - max-width: 1000px; + max-width: 1200px; } .ticket-sidebar { diff --git a/templates/comments/edit-ajax.html b/templates/comments/edit-ajax.html index 2bdbd14185..4c88afa9d8 100644 --- a/templates/comments/edit-ajax.html +++ b/templates/comments/edit-ajax.html @@ -1,4 +1,4 @@ -