From 3fffb32417371b24625183921a7ed9b076b65769 Mon Sep 17 00:00:00 2001 From: Nguyen Viet Dung <29406816+magnified103@users.noreply.github.com> Date: Fri, 11 Oct 2024 00:23:54 +0700 Subject: [PATCH] Enhanced import ui --- dmoj/settings.py | 3 +++ dmoj/urls.py | 11 +++++---- judge/template_context.py | 4 ++++ judge/views/problem_transfer.py | 22 +++++++++++------ templates/problem/import.html | 30 ++++++++++++++++-------- templates/problem/problem-list-tabs.html | 3 +++ 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/dmoj/settings.py b/dmoj/settings.py index d83f1176c..440bb4099 100755 --- a/dmoj/settings.py +++ b/dmoj/settings.py @@ -118,6 +118,8 @@ VNOJ_LONG_QUEUE_ALERT_THRESHOLD = 10 # Transfer host +VNOJ_PROBLEM_ENABLE_IMPORT = False +VNOJ_PROBLEM_ENABLE_EXPORT = False VNOJ_PROBLEM_IMPORT_HOST = 'https://oj.vnoi.info' VNOJ_PROBLEM_IMPORT_SECRET = '' VNOJ_PROBLEM_IMPORT_TIMEOUT = 5 # in seconds @@ -502,6 +504,7 @@ 'judge.template_context.site_theme', 'judge.template_context.misc_config', 'judge.template_context.math_setting', + 'judge.template_context.site_setting', 'social_django.context_processors.backends', 'social_django.context_processors.login_redirect', ], diff --git a/dmoj/urls.py b/dmoj/urls.py index 183d81950..0e612cdc0 100644 --- a/dmoj/urls.py +++ b/dmoj/urls.py @@ -116,11 +116,6 @@ def paged_list_view(view, name): path('/suggest', problem.ProblemSuggest.as_view(), name='problem_suggest'), path('/create', problem.ProblemCreate.as_view(), name='problem_create'), path('/import-polygon', problem.ProblemImportPolygon.as_view(), name='problem_import_polygon'), - re_path('/export/(?P[a-zA-Z0-9_-]{48})/', include([ - path('', ProblemExportView.as_view(), name='problem_export'), - path('select/', ProblemExportSelect2View.as_view(), name='problem_export_select2_ajax'), - ])), - path('/import', ProblemImportView.as_view(), name='problem_import'), ])), path('problem/', include([ @@ -427,6 +422,12 @@ def paged_list_view(view, name): ])), path('magazine/', MagazinePage.as_view(), name='magazine'), + + re_path('^problem-export/(?P[a-zA-Z0-9_-]{48})', include([ + path('', ProblemExportView.as_view(), name='problem_export'), + path('/select', ProblemExportSelect2View.as_view(), name='problem_export_select2_ajax'), + ])), + path('problem-import', ProblemImportView.as_view(), name='problem_import'), ] favicon_paths = ['apple-touch-icon-180x180.png', 'apple-touch-icon-114x114.png', 'android-chrome-72x72.png', diff --git a/judge/template_context.py b/judge/template_context.py index e055cbdc7..24b549aee 100644 --- a/judge/template_context.py +++ b/judge/template_context.py @@ -106,3 +106,7 @@ def math_setting(request): if engine == 'auto': engine = 'mml' if bool(settings.MATHOID_URL) and caniuse.mathml == SUPPORT else 'jax' return {'MATH_ENGINE': engine, 'REQUIRE_JAX': engine == 'jax', 'caniuse': caniuse} + + +def site_setting(request): + return {'VNOJ_PROBLEM_ENABLE_IMPORT': settings.VNOJ_PROBLEM_ENABLE_IMPORT} \ No newline at end of file diff --git a/judge/views/problem_transfer.py b/judge/views/problem_transfer.py index 06f8b3e15..f8e8cbbea 100644 --- a/judge/views/problem_transfer.py +++ b/judge/views/problem_transfer.py @@ -29,6 +29,8 @@ class ProblemExportMixin: def setup(self, request, *args, **kwargs): + if not settings.VNOJ_PROBLEM_ENABLE_EXPORT: + raise Http404() super().setup(request, *args, **kwargs) try: id, secret = struct.unpack('>I32s', base64.urlsafe_b64decode(kwargs['secret'])) @@ -115,18 +117,19 @@ def get_problem_export_url(host=settings.VNOJ_PROBLEM_IMPORT_HOST, secret=settin class ProblemImportForm(Form): problem = CharField(max_length=32, validators=[RegexValidator('^[a-z0-9_]+$', _('Problem code must be ^[a-z0-9_]+$'))]) - code = CharField(max_length=32, validators=[RegexValidator('^[a-z0-9_]+$', _('Problem code must be ^[a-z0-9_]+$'))]) + new_code = CharField(max_length=32, validators=[RegexValidator('^[a-z0-9_]+$', + _('Problem code must be ^[a-z0-9_]+$'))]) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['problem'].widget = HeavySelect2Widget(data_url=get_problem_export_select_url(), attrs={'style': 'width: 100%'}) - def clean_code(self): - code = self.cleaned_data['code'] - if Problem.objects.filter(code=code).exists(): + def clean_new_code(self): + new_code = self.cleaned_data['new_code'] + if Problem.objects.filter(code=new_code).exists(): raise ValidationError(_('Problem with code already exists.')) - return code + return new_code def clean(self): key_info = requests.get(get_problem_export_url(), timeout=settings.VNOJ_PROBLEM_IMPORT_TIMEOUT).json() @@ -142,12 +145,14 @@ class ProblemImportView(TitleMixin, FormView): form_class = ProblemImportForm def form_valid(self, form): - problem_info = requests.post(get_problem_export_url(), data={'code': form.cleaned_data['problem']}, timeout=settings.VNOJ_PROBLEM_IMPORT_TIMEOUT).json() + problem_info = requests.post(get_problem_export_url(), + data={'code': form.cleaned_data['problem']}, + timeout=settings.VNOJ_PROBLEM_IMPORT_TIMEOUT).json() if not problem_info: raise Http404('Request timed out') problem = Problem() - problem.code = form.cleaned_data['code'] + problem.code = form.cleaned_data['new_code'] problem.name = problem_info['name'] problem.description = problem_info['description'] problem.time_limit = problem_info['time_limit'] @@ -157,6 +162,7 @@ def form_valid(self, form): problem.short_circuit = problem_info['short_circuit'] problem.group = ProblemGroup.objects.order_by('id').first() # Uncategorized problem.date = timezone.now() + problem.is_manually_managed = True with revisions.create_revision(atomic=True): problem.save() problem.allowed_languages.set(Language.objects.filter(include_in_problem=True)) @@ -168,6 +174,8 @@ def form_valid(self, form): return HttpResponseRedirect(reverse('problem_edit', args=(problem.code,))) def dispatch(self, request, *args, **kwargs): + if not settings.VNOJ_PROBLEM_ENABLE_IMPORT: + raise Http404() if not request.user.is_superuser: raise PermissionDenied() return super().dispatch(request, *args, **kwargs) diff --git a/templates/problem/import.html b/templates/problem/import.html index ee017f9df..2facdee14 100644 --- a/templates/problem/import.html +++ b/templates/problem/import.html @@ -2,21 +2,31 @@ {% block media %} {{ form.media.css }} + {% endblock %} {% block js_media %} {{ form.media.js }} {% endblock %} +{% block title_ruler %}{% endblock %} + +{% block title_row %} + {% set tab = 'import' %} + {% include "problem/problem-list-tabs.html" %} +{% endblock %} + {% block body %} -
- {% if form.errors %} -
- {{ form.non_field_errors() }} -
- {% endif %} - {% csrf_token %} - {{ form.as_p() }} -

-
+
+
+ {% if form.non_field_errors() %} +
+ {{ form.non_field_errors() }} +
+ {% endif %} + {% csrf_token %} + {{ form.as_table() }}
+

+
+
{% endblock %} diff --git a/templates/problem/problem-list-tabs.html b/templates/problem/problem-list-tabs.html index cc415067d..bd72bea87 100644 --- a/templates/problem/problem-list-tabs.html +++ b/templates/problem/problem-list-tabs.html @@ -12,6 +12,9 @@ {{ make_tab('suggest', 'fa-list', url('problem_suggest_list'), _('Suggest')) }} {% endif %} {% if request.user.is_superuser %} + {% if VNOJ_PROBLEM_ENABLE_IMPORT %} + {{ make_tab('import', 'fa-cloud-download', url('problem_import'), _('Import')) }} + {% endif %} {{ make_tab('admin', 'fa-edit', url('admin:judge_problem_changelist'), _('Admin')) }} {% endif %} {% endblock %}