diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..19029dc --- /dev/null +++ b/forms.py @@ -0,0 +1,6 @@ +from django import forms + + + +class DummyManagerForm(forms.Form): + dummy_field = forms.CharField() diff --git a/hooks.py b/hooks.py new file mode 100644 index 0000000..8f0b9d7 --- /dev/null +++ b/hooks.py @@ -0,0 +1,45 @@ +from django.template import loader + +from utils import setting_handler +from submission import forms +from plugins.coversheet.models import Coversheet + + +def coversheet_upload(context): + request = context.get('request') + coversheet_enabled = setting_handler.get_setting( + setting_group_name='plugin:coversheet', + setting_name='enable_coversheet_upload', + journal=request.journal, + ).processed_value + + if not coversheet_enabled: + return '' + + coversheet_text = setting_handler.get_setting( + setting_group_name='plugin:coversheet', + setting_name='coversheet_text', + journal=request.journal, + ).processed_value + + coversheet_form = forms.FileDetails( + initial={ + "label": 'Cover sheet', + } + ) + + coversheets = Coversheet.objects.filter( + article=context.get('article'), + ) + + # Convert RequestContext to plain dict + context_dict = context.flatten() + context_dict['coversheet_text'] = coversheet_text + context_dict['coversheet_form'] = coversheet_form + context_dict['coversheets'] = coversheets + + template = loader.get_template('coversheet/upload.html') + return template.render( + context=context_dict, + request=request, + ) diff --git a/install/settings.json b/install/settings.json new file mode 100644 index 0000000..86a4cb5 --- /dev/null +++ b/install/settings.json @@ -0,0 +1,32 @@ +[ + { + "group": { + "name": "plugin:coversheet" + }, + "setting": { + "description": "Enable coversheet upload for this journal.", + "is_translatable": true, + "name": "enable_coversheet_upload", + "pretty_name": "Enable Coversheet Upload (PLUGIN)", + "type": "boolean" + }, + "value": { + "default": false + } + }, + { + "group": { + "name": "plugin:coversheet" + }, + "setting": { + "description": "Text displayed above the coversheet upload block", + "is_translatable": true, + "name": "coversheet_text", + "pretty_name": "Coversheet Text (PLUGIN)", + "type": "char" + }, + "value": { + "default": "Upload a coversheet for your article." + } + } +] diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py new file mode 100644 index 0000000..f51ef0e --- /dev/null +++ b/migrations/0001_initial.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.20 on 2025-09-05 14:29 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('core', '0110_account_accessible_theme'), + ('submission', '0088_auto_20250506_1214'), + ] + + operations = [ + migrations.CreateModel( + name='Coversheet', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='submission.article')), + ('file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.file')), + ], + ), + ] diff --git a/migrations/__init__.py b/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models.py b/models.py new file mode 100644 index 0000000..712c306 --- /dev/null +++ b/models.py @@ -0,0 +1,9 @@ +from django.db import models + +from submission.models import Article +from core.models import File + + +class Coversheet(models.Model): + article = models.ForeignKey(Article, on_delete=models.CASCADE) + file = models.ForeignKey(File, on_delete=models.CASCADE) \ No newline at end of file diff --git a/plugin_settings.py b/plugin_settings.py new file mode 100644 index 0000000..dbddf3a --- /dev/null +++ b/plugin_settings.py @@ -0,0 +1,49 @@ +from utils import plugins +from utils.install import update_settings + +PLUGIN_NAME = 'Coversheet Plugin' +DISPLAY_NAME = 'Coversheet' +DESCRIPTION = 'A plugin to allow authors to upload a cover sheet.' +AUTHOR = 'Andy Byers' +VERSION = '0.1' +SHORT_NAME = 'coversheet' +MANAGER_URL = 'coversheet_manager' +JANEWAY_VERSION = "1.3.8" + + + +class CoversheetPlugin(plugins.Plugin): + plugin_name = PLUGIN_NAME + display_name = DISPLAY_NAME + description = DESCRIPTION + author = AUTHOR + short_name = SHORT_NAME + manager_url = MANAGER_URL + + version = VERSION + janeway_version = JANEWAY_VERSION + + + +def install(): + CoversheetPlugin.install() + update_settings( + file_path='plugins/coversheet/install/settings.json' + ) + + + +def hook_registry(): + # On site load, the load function is run for each installed plugin to generate + # a list of hooks. + return { + 'submission_files': + { + 'module': 'plugins.coversheet.hooks', + 'function': 'coversheet_upload', + }, + } + + +def register_for_events(): + pass diff --git a/templates/coversheet/manager.html b/templates/coversheet/manager.html new file mode 100644 index 0000000..e31cda2 --- /dev/null +++ b/templates/coversheet/manager.html @@ -0,0 +1,15 @@ +{% extends "admin/core/base.html" %} +{% load foundation %} + +{% block title %}Coversheet Manager{% endblock %} + +{% block body %} +
+
+

Management Form

+
+
+ {{ form|foundation }} +
+
+{% endblock body %} \ No newline at end of file diff --git a/templates/coversheet/upload.html b/templates/coversheet/upload.html new file mode 100644 index 0000000..390f6c4 --- /dev/null +++ b/templates/coversheet/upload.html @@ -0,0 +1,83 @@ +
+

{% trans 'Cover Sheet' %}

+
+
+
+ +  {% trans "Upload" %} + +
+
+ + + + + + + + {% csrf_token %} + {% for coversheet in coversheets %} + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Label" %}{% trans "File Name" %}
{{ coversheet.file.label }}{{ coversheet.file }} + +
{% trans "No files uploaded" %}
+
+
+ + +{% load foundation %} +{% load i18n %} + +
+
+
+
+ + {% trans "Add New File" %} +
+
+
+
+

{{ coversheet_text }}

+
+
+ {% csrf_token %} +
+
+ +
+
+ {{ coversheet_form|foundation }} + + +
+
+
+
\ No newline at end of file diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..fbf352d --- /dev/null +++ b/urls.py @@ -0,0 +1,9 @@ +from django.urls import re_path + +from plugins.coversheet import views + + +urlpatterns = [ + re_path(r'^manager/$', views.manager, name='coversheet_manager'), + re_path(r'^upload/(?P\d+)$', views.coversheet_upload, name='coversheet_upload'), +] diff --git a/views.py b/views.py new file mode 100644 index 0000000..3b71169 --- /dev/null +++ b/views.py @@ -0,0 +1,66 @@ +from django.shortcuts import render, get_object_or_404, redirect, reverse +from django.contrib import messages +from django.contrib.auth.decorators import login_required + +from submission import models, forms, decorators +from core import files +from plugins.coversheet.models import Coversheet +from security.decorators import article_is_not_submitted, article_edit_user_required, submission_authorised + + +def manager(request): + form = forms.DummyManagerForm() + + template = 'coversheet/manager.html' + context = { + 'form': form, + } + + return render(request, template, context) + + +@login_required +@decorators.submission_is_enabled +@article_is_not_submitted +@article_edit_user_required +@submission_authorised +def coversheet_upload(request, article_id): + article = get_object_or_404( + models.Article, + id=article_id, + journal=request.journal, + ) + if "coversheet" in request.POST: + coversheet_form = forms.FileDetails(request.POST) + uploaded_file = request.FILES.get("file") + if coversheet_form.is_valid(): + new_file = files.save_file_to_article( + uploaded_file, + article, + request.user, + ) + new_file.label = coversheet_form.cleaned_data["label"] + new_file.description = coversheet_form.cleaned_data["description"] + new_file.save() + Coversheet.objects.create( + article=article, + file=new_file, + ) + + else: + for field, errors in coversheet_form.errors.items(): + for error in errors: + messages.error( + request, + f"{field}: {error}", + ) + + else: + messages.error( + request, + "No file selected for upload.", + ) + + return redirect( + reverse("submit_files", kwargs={"article_id": article_id}), + ) \ No newline at end of file