Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
0b659ed
addition patch method api/articles/<str:abstract__pid>/status/
eliselavy Oct 13, 2025
fd7d43d
integration run preflight action - post save
eliselavy Oct 14, 2025
3a4e5c2
(feat) send_to_ojs endpoint started + OJS_API_KEY and OJS_URL added t…
salaun-marion Jan 21, 2026
eadeac6
(feat) different methods created for the different stage of OJS submi…
salaun-marion Jan 21, 2026
c898776
Merge pull request #332 from C2DH/324-article-status-copyediting
eliselavy Jan 23, 2026
1e23e3b
(fix) schema change from pids to pid and url /api/articles/ojs listed
salaun-marion Jan 26, 2026
2cff6d3
(feat) seapration of the process for each author + generation of the pdf
salaun-marion Jan 26, 2026
da6ca96
(fix) /api/article/ojs works locally
salaun-marion Jan 30, 2026
24ec9f4
(remove) code to generate peer review pdf and email
salaun-marion Jan 30, 2026
a553706
(test) add unit test for send_to_ojs
salaun-marion Feb 4, 2026
e1e2e58
Merge branch 'develop' into 244-send-submission-through-ojs-post-route
salaun-marion Feb 4, 2026
b8105c9
Merge pull request #348 from C2DH/244-send-submission-through-ojs-pos…
salaun-marion Feb 4, 2026
4fb7edf
(feat) get country code with ROR API
salaun-marion Feb 4, 2026
64a79d7
(fix) mispelling githup to github
salaun-marion Feb 9, 2026
bcde30b
(refactor) logger move to utils
salaun-marion Feb 9, 2026
a4b5dbf
(feat) get submission counter from ojs endpoint created
salaun-marion Feb 9, 2026
2e1d04b
(test) separating clearly the 2 endpoints for ojs
salaun-marion Feb 10, 2026
2f5edba
(feat) add submission_id to Article model
salaun-marion Feb 10, 2026
4ccf7b6
(feat) safeguard for article.data.title
salaun-marion Feb 11, 2026
0fac0c9
(feat) different methods created for the copy-editing step
eliselavy Feb 13, 2026
342188c
(test) fix the test for send_to_ojs
salaun-marion Feb 16, 2026
38add40
(test) add mock to prevent blank submission to be created to OJS
salaun-marion Feb 16, 2026
c2555d1
Merge pull request #351 from C2DH/244-send-submission-through-ojs-pos…
salaun-marion Feb 16, 2026
4f6d801
(feat) altcha implementation with create _challenge and GET route
salaun-marion Feb 16, 2026
8b3d051
(feat) add cors headers for the recaptcha
salaun-marion Feb 16, 2026
aaa4759
(feat) validation of the captcha before creating abstract submission …
salaun-marion Feb 16, 2026
09b8589
(test) test_abstract_submit adapted for captcha
salaun-marion Feb 17, 2026
c38a012
(test) cors_allowed_origins added for django unit test
salaun-marion Feb 17, 2026
2b00158
(test) add altcha hmac key
salaun-marion Feb 17, 2026
5ceac9f
Merge pull request #353 from C2DH/943-captcha-switch-to-another-captcha
salaun-marion Feb 17, 2026
ce6dadd
(fix) fixing typos for test
salaun-marion Feb 17, 2026
b8ff992
Merge pull request #354 from C2DH/943-captcha-switch-to-another-captcha
salaun-marion Feb 17, 2026
3eafd1d
(fix) update requirements.txt with altcha and django-cors-headers
salaun-marion Feb 17, 2026
30f8aae
Merge pull request #355 from C2DH/943-captcha-switch-to-another-captcha
salaun-marion Feb 17, 2026
d39d7a8
[fix] trigger_workflow_and_wait
eliselavy Feb 17, 2026
4ca1b56
[fix] ensure_pandoc_workflow
eliselavy Feb 18, 2026
0d51089
[feature] CopyEditingHandler
eliselavy Feb 18, 2026
53117ea
[feature] peer-review handler
eliselavy Feb 18, 2026
9a55982
[feature] handler PUBLISHED - save_citation no more cleery task
eliselavy Feb 19, 2026
9b17eb4
(review) add variables to .env + renaming + merging function to api e…
salaun-marion Feb 26, 2026
920c75b
(review) remove sending email code fromn copyediting handler
salaun-marion Feb 26, 2026
045447b
(review) changing send_docx_email to POST to be able to adapt body in FE
salaun-marion Feb 26, 2026
5a58d8b
(fix) removed flake8 linter for ruff configuration pyproject.yml
salaun-marion Feb 26, 2026
5b6701e
Merge branch 'develop' into 272-dashboard-create-one-endpoint-for-art…
salaun-marion Feb 26, 2026
796a02a
Merge pull request #357 from C2DH/272-dashboard-create-one-endpoint-f…
salaun-marion Feb 26, 2026
50a03d4
(fix) formatting python file ojs + add rule to have primary_contact l…
salaun-marion Feb 27, 2026
8e38a4c
(fix) add doc strings
salaun-marion Feb 27, 2026
8f942d5
(test) fix test
salaun-marion Feb 27, 2026
91f722f
Merge pull request #358 from C2DH/244-send-submission-through-ojs-pos…
salaun-marion Feb 27, 2026
c10b8d1
(fix) add env variables for test CI
salaun-marion Feb 27, 2026
ce355d8
Merge pull request #359 from C2DH/244-send-submission-through-ojs-pos…
salaun-marion Feb 27, 2026
4b9311e
(fix) move logging.info after owner, repo variable for linter
salaun-marion Feb 27, 2026
4b7c6cb
Merge pull request #360 from C2DH/272-dashboard-create-one-endpoint-f…
salaun-marion Feb 27, 2026
d727c1d
(feat) linkedinId added
salaun-marion Mar 2, 2026
85a65e4
(feat) linkedin id makemigrations
salaun-marion Mar 2, 2026
d9c2222
Merge pull request #361 from C2DH/949-social-network-add-linkedin-to-…
salaun-marion Mar 3, 2026
f1e444b
(fix) reactivate sending email to author and admin
salaun-marion Mar 5, 2026
f6760ce
(fix) send_mail reimported
salaun-marion Mar 5, 2026
70631af
Merge pull request #362 from C2DH/949-social-network-add-linkedin-to-…
salaun-marion Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
SECRET_KEY=ccscscsc
ALLOWED_HOSTS=127.0.0.1
ALTCHA_HMAC_KEY=secret_key
BLUESKY_JDH_ACCOUNT=****.bsky.social
BLUESKY_JDH_PASSWORD=secret_key
CORS_ALLOW_CREDENTIALS=True
CORS_ALLOWED_ORIGINS=http://127.0.0.1
CSRF_TRUSTED_ORIGINS=http://127.0.0.1
DATABASE_ENGINE=django.db.backends.sqlite3
DATABASE_NAME=db.sqlite3
DATABASE_USER=db
DATABASE_PASSWORD=pwd
ALLOWED_HOSTS=127.0.0.1
CSRF_TRUSTED_ORIGINS=http://127.0.0.1
EMAIL_HOST=smtp
EMAIL_PORT=poort
DRF_RECAPTCHA_SECRET_KEY=secret_key
NUM_CHARS_FINGERPRINT=10
JDH_ORCID_API_TOKEN=secret_key
SECRET_KEY=ccscscsc
EMAIL_HOST=smtp
EMAIL_PORT=port
FACEBOOK_JDH_PAGE_ID=secret_key
FACEBOOK_JDH_ACCESS_TOKEN=secret_key
GITHUB_ACCESS_TOKEN=secret_key
CORS_ALLOW_CREDENTIALS=True
CORS_ALLOWED_ORIGINS=http://127.0.0.1
JDH_ORCID_API_TOKEN=secret_key
NUM_CHARS_FINGERPRINT=10
SESSION_COOKIE_SAMESITE=None
SESSION_COOKIE_SECURE=True
FACEBOOK_JDH_PAGE_ID=secret_key
FACEBOOK_JDH_ACCESS_TOKEN=secret_key
BLUESKY_JDH_ACCOUNT=****.bsky.social
BLUESKY_JDH_PASSWORD=secret_key
OJS_API_KEY_TOKEN=secret_key
OJS_API_URL=http://ojs.journalofdigitalhistory.org
5 changes: 0 additions & 5 deletions .flake8

This file was deleted.

7 changes: 6 additions & 1 deletion .github/workflows/run_unit_tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Django CI
name: Unit Tests Django CI

on:
pull_request:
Expand Down Expand Up @@ -45,6 +45,7 @@ jobs:

- name: Run tests
env:
ALTCHA_HMAC_KEY: ${{ secrets.ALTCHA_HMAC_KEY }}
SECRET_KEY: default-secret-key-for-testing
DATABASE_ENGINE: django.db.backends.postgresql_psycopg2
DATABASE_NAME: test_db
Expand All @@ -53,6 +54,7 @@ jobs:
DATABASE_HOST: localhost
DATABASE_PORT: 5432
ALLOWED_HOSTS: localhost
CORS_ALLOWED_ORIGINS: http://127.0.0.1
CSRF_TRUSTED_ORIGINS: http://127.0.0.1
DRF_RECAPTCHA_SECRET_KEY: default-recaptcha-secret-key
EMAIL_HOST: smtp.example.com
Expand All @@ -66,6 +68,9 @@ jobs:
BLUESKY_JDH_PASSWORD: ${{ secrets.BLUESKY_JDH_PASSWORD }}
FACEBOOK_JDH_PAGE_ID: ${{ secrets.FACEBOOK_JDH_PAGE_ID }}
FACEBOOK_JDH_ACCESS_TOKEN: ${{ secrets.FACEBOOK_JDH_ACCESS_TOKEN }}
OJS_API_KEY_TOKEN: default-token
OJS_API_URL: https://ojs-api-url-example.com
COPY_EDITOR_ADDRESS: copy-editor-address@mail.com
run: |
pipenv run ./manage.py test

Expand Down
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ webcolors = "==24.11.1"
webencodings = "==0.5.1"
websocket-client = "==1.8.0"
zopfli = "==0.2.3.post1"
altcha = "*"
django-cors-headers = "*"

[requires]
python_version = "3.12"
20 changes: 19 additions & 1 deletion Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 15 additions & 3 deletions jdh/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path
import os
import sys
from pathlib import Path

from .base import get_env_variable

# Build paths inside the project like this: BASE_DIR / 'subdir'.
Expand All @@ -30,18 +31,23 @@

DJANGO_LOG_LEVEL = get_env_variable("DJANGO_LOG_LEVEL", "DEBUG")

CORS_ALLOWED_ORIGINS = get_env_variable("CORS_ALLOWED_ORIGINS", "").split(",")

CSRF_TRUSTED_ORIGINS = get_env_variable("CSRF_TRUSTED_ORIGINS", "").split(",")

ALLOWED_HOSTS = get_env_variable("ALLOWED_HOSTS", "").split(",")

ALTCHA_HMAC_KEY = get_env_variable("ALTCHA_HMAC_KEY", "").split(",")

DRF_RECAPTCHA_SECRET_KEY = get_env_variable(
"DRF_RECAPTCHA_SECRET_KEY", "default-recaptacha-secret-key"
)
).split(",")


# Application definition

INSTALLED_APPS = [
"corsheaders",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
Expand Down Expand Up @@ -79,6 +85,7 @@
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
'corsheaders.middleware.CorsMiddleware',
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
Expand Down Expand Up @@ -278,11 +285,16 @@
DEFAULT_TO_EMAIL = get_env_variable("DEFAULT_TO_EMAIL", "jdh.admin@uni.lu")

# Github API

GITHUB_ACCESS_TOKEN = get_env_variable("GITHUB_ACCESS_TOKEN")

# Social network
BLUESKY_JDH_ACCOUNT = get_env_variable("BLUESKY_JDH_ACCOUNT")
BLUESKY_JDH_PASSWORD = get_env_variable("BLUESKY_JDH_PASSWORD")
FACEBOOK_JDH_PAGE_ID = get_env_variable("FACEBOOK_JDH_PAGE_ID")
FACEBOOK_JDH_ACCESS_TOKEN = get_env_variable("FACEBOOK_JDH_ACCESS_TOKEN")

# OJS API
OJS_API_KEY_TOKEN = get_env_variable("OJS_API_KEY_TOKEN", "default")
OJS_API_URL = get_env_variable("OJS_API_URL", "http://ojs.journalofdigitalhistory.org")

COPY_EDITOR_ADDRESS = get_env_variable("COPY_EDITOR_ADDRESS", "")
4 changes: 2 additions & 2 deletions jdhapi/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from .tasks import (
save_article_fingerprint,
save_article_specific_content,
save_citation,
save_libraries,
save_references,
)
from .utils.articles import save_citation
from import_export.admin import ExportActionMixin
from django.utils.html import format_html

Expand All @@ -37,7 +37,7 @@ def save_notebook_specific_cell(modeladmin, request, queryset):

def save_article_citation(modeladmin, request, queryset):
for article in queryset:
save_citation.delay(article_id=article.pk)
save_citation(article_id=article.pk)


save_article_citation.short_description = "3: Generate citation"
Expand Down
2 changes: 1 addition & 1 deletion jdhapi/forms/articleForm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# import marko
from django import forms
from jdhapi.models import Article, Abstract
from jdhapi.utils.gitup_repository import is_socialmediacover_exist
from jdhapi.utils.github_repository import is_socialmediacover_exist
import logging
import datetime
from django.http import Http404
Expand Down
18 changes: 18 additions & 0 deletions jdhapi/migrations/0052_article_ojs_submission_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.6 on 2026-02-09 16:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('jdhapi', '0051_remove_abstract_issue'),
]

operations = [
migrations.AddField(
model_name='article',
name='ojs_submission_id',
field=models.IntegerField(blank=True, default=None, null=True),
),
]
23 changes: 23 additions & 0 deletions jdhapi/migrations/0053_author_linkedin_id_alter_article_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2026-03-02 11:01

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('jdhapi', '0052_article_ojs_submission_id'),
]

operations = [
migrations.AddField(
model_name='author',
name='linkedin_id',
field=models.CharField(blank=True, max_length=100, null=True),
),
migrations.AlterField(
model_name='article',
name='status',
field=models.CharField(choices=[('DRAFT', 'Draft'), ('TECHNICAL_REVIEW', 'Technical review'), ('PEER_REVIEW', 'Peer review'), ('DESIGN_REVIEW', 'Design review'), ('COPY_EDITING', 'Copy editing'), ('PUBLISHED', 'Published')], default='DRAFT', max_length=25),
),
]
55 changes: 10 additions & 45 deletions jdhapi/models/article.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import logging
import marko

from django.conf import settings

from django.core.mail import EmailMessage
from django.db import models
from django.template.loader import render_to_string

from lxml import html
from model_utils import FieldTracker
from weasyprint import HTML

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -43,7 +35,6 @@ class Article(models.Model):
Methods:
get_kernel_language(): Returns the kernel language based on the 'tool' tag.
__str__(): Returns the title of the abstract.
send_email_if_peer_review(): Sends an email with a PDF attachment if the article is in peer review status.
"""

class Status(models.TextChoices):
Expand All @@ -63,7 +54,14 @@ class Status(models.TextChoices):
"DESIGN_REVIEW",
"Design review",
)
PUBLISHED = "PUBLISHED", "Published"
COPY_EDITING = (
"COPY_EDITING",
"Copy editing",
)
PUBLISHED = (
"PUBLISHED",
"Published",
)

class CopyrightType(models.TextChoices):
DRAFT = (
Expand Down Expand Up @@ -138,7 +136,7 @@ class RepositoryType(models.TextChoices):
blank=True,
null=True,
help_text="Url to find here https://data.journalofdigitalhistory.org/",
) # New field for Dataverse URL
)
publication_date = models.DateTimeField(blank=True, null=True)
copyright_type = models.CharField(
max_length=15,
Expand All @@ -162,6 +160,7 @@ class RepositoryType(models.TextChoices):
)
tags = models.ManyToManyField("jdhapi.Tag", blank=True)
authors = models.ManyToManyField("jdhapi.Author", through="Role")
ojs_submission_id = models.IntegerField(null=True, blank=True, default=None)

def get_kernel_language(self):
tool_tags = self.tags.filter(category="tool")
Expand All @@ -174,37 +173,3 @@ def get_kernel_language(self):

def __str__(self):
return self.abstract.title

def send_email_if_peer_review(self):
if self.status == self.Status.PEER_REVIEW:
# Render the PDF template
template = "jdhseo/peer_review.html"
if "title" in self.data:
articleTitle = html.fromstring(
marko.convert(self.data["title"][0])
).text_content()
context = {"article": self, "articleTitle": articleTitle}
html_string = render_to_string(template, context)

# Generate the PDF
pdf_file = HTML(string=html_string).write_pdf()
logger.info("Pdf generated")
filename = "peer_review_" + self.abstract.pid + ".pdf"
# Save the PDF to a file
# with open(filename, 'wb') as f:
# f.write(pdf_file)
# logger.info("Pdf saved")
# Create an email message with the PDF attachment
subject = f"{articleTitle} can been sent to peer review!"
body = "Please find attached the links useful for the peer review."
from_email = settings.DEFAULT_FROM_EMAIL
to_email = settings.DEFAULT_TO_EMAIL
email = EmailMessage(subject, body, from_email, [to_email])
email.attach(filename, pdf_file, "application/pdf")

# Send the email
try:
email.send()
logger.info("Email sent")
except Exception as e:
print(f"Error sending email: {str(e)}")
1 change: 1 addition & 0 deletions jdhapi/models/author.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Author(models.Model):
github_id = models.CharField(max_length=39, null=True, blank=True)
bluesky_id = models.CharField(max_length=255, null=True, blank=True)
facebook_id = models.CharField(max_length=50, null=True, blank=True)
linkedin_id = models.CharField(max_length=100, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
country = CountryField(blank=True, null=True)

Expand Down
1 change: 1 addition & 0 deletions jdhapi/serializers/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ class Meta:
"tags",
"issue",
"authors",
"ojs_submission_id",
"fingerprint",
]
Loading