From f1c3054fd2b2ed83782a826d202e1e6afd48f50c Mon Sep 17 00:00:00 2001 From: Aga Date: Fri, 9 Jan 2026 13:10:37 +0000 Subject: [PATCH 01/10] add warning --- portality/forms/application_processors.py | 6 ++++++ .../management/admin/maned_application.html | 18 ++++++++++++++++++ portality/templates-v2/management/base.html | 1 + portality/view/admin.py | 14 +++++++++++--- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/portality/forms/application_processors.py b/portality/forms/application_processors.py index b000dbbc06..0ceabd793f 100644 --- a/portality/forms/application_processors.py +++ b/portality/forms/application_processors.py @@ -393,6 +393,12 @@ def finalise(self, account, save_target=True, email_alert=True): self.add_alert(Messages.FORMS__APPLICATION_PROCESSORS__ADMIN_APPLICATION__FINALISE__COULD_NOT_UNREJECT) return + # is the application is being rejected now? + if self.target.application_status == constants.APPLICATION_STATUS_REJECTED and self.source.application_status != constants.APPLICATION_STATUS_REJECTED: + self.info = "is being rejected" + else: + self.info = "gibbirish" + # if this application is being accepted, then do the conversion to a journal if self.target.application_status == constants.APPLICATION_STATUS_ACCEPTED: j = applicationService.accept_application(self.target, account) diff --git a/portality/templates-v2/management/admin/maned_application.html b/portality/templates-v2/management/admin/maned_application.html index 0c7bbe8086..5400033d90 100644 --- a/portality/templates-v2/management/admin/maned_application.html +++ b/portality/templates-v2/management/admin/maned_application.html @@ -13,6 +13,24 @@ {% block page_title %}{% if obj.application_type == constants.APPLICATION_TYPE_UPDATE_REQUEST %}Update Request{% else %}Application{% endif %}: {{ obj.bibjson().title }}{% endblock %} {% block body_id %}apply{% endblock %} +{% block permanent_warnings %} + + {% if obj.application_status == "rejected" and continuation_info.id %} +
+
+

This application has been rejected. We found a related older journal record. You may want to withdraw it.
+ {{ continuation_info.title }} +

+ +
+
+ {% endif %} +{% endblock %} + {% block admin_content scoped %} {% include "management/_application-form/includes/_editorial_form_body.html" %} diff --git a/portality/templates-v2/management/base.html b/portality/templates-v2/management/base.html index 46da453e3c..29390ac0d2 100644 --- a/portality/templates-v2/management/base.html +++ b/portality/templates-v2/management/base.html @@ -169,6 +169,7 @@

+ {% block permanent_warnings %}{% endblock %} {% include "includes/_flash_notification.html" %} {% block management_content %}{% endblock %} diff --git a/portality/view/admin.py b/portality/view/admin.py index 530f631d5e..cfb14d5c65 100644 --- a/portality/view/admin.py +++ b/portality/view/admin.py @@ -422,7 +422,7 @@ def update_requests(): @write_required() @login_required @ssl_required -def application(application_id): +def application(application_id, **kwargs): auth_svc = DOAJ.authorisationService() application_svc = DOAJ.applicationService() @@ -448,8 +448,15 @@ def application(application_id): if request.method == "GET": fc.processor(source=ap) + first_rejection = request.args.get("info") == "is being rejected" + continuation_info = {"first_rejection": first_rejection} + replaces = Journal.find_by_issn(ap.bibjson().replaces) + if replaces: + r = replaces[0] + continuation_info["id"] = r.id + continuation_info["title"] = r.bibjson().title return fc.render_template(obj=ap, lock=lockinfo, form_diff=form_diff, - current_journal=current_journal, lcc_tree=lcc_jstree, autochecks=autochecks) + current_journal=current_journal, lcc_tree=lcc_jstree, autochecks=autochecks, continuation_info=continuation_info) elif request.method == "POST": processor = fc.processor(formdata=request.form, source=ap) @@ -461,10 +468,11 @@ def application(application_id): # for f in processor.form.resettedFields: # text += "
field: {}, invalid value: {}, new value: {}".format(f["name"], f["data"], f["default"]) # flash(text, 'info') + print(processor.info) flash('Application updated.', 'success') for a in processor.alert: flash_with_url(a, "success") - return redirect(url_for("admin.application", application_id=ap.id, _anchor='done')) + return redirect(url_for("admin.application", application_id=ap.id, _anchor='done', info=processor.info)) except Exception as e: flash("unexpected field " + str(e)) return redirect(url_for("admin.application", application_id=ap.id, _anchor='cannot_edit')) From 989be7fc8f5bcb8a759a8c5da5f63359a9e2b564 Mon Sep 17 00:00:00 2001 From: Aga Date: Fri, 9 Jan 2026 14:02:21 +0000 Subject: [PATCH 02/10] add styles --- cms/sass/base/_general.scss | 10 +++++++++ cms/sass/components/_alert.scss | 21 +++++++++++++++++++ portality/static/js/application_form.js | 6 ++++++ .../management/admin/maned_application.html | 16 +++++++------- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/cms/sass/base/_general.scss b/cms/sass/base/_general.scss index 0cc4ed5ceb..bfbc9e33c7 100644 --- a/cms/sass/base/_general.scss +++ b/cms/sass/base/_general.scss @@ -333,3 +333,13 @@ fieldset { height: 1em; width: auto; } + +.focus-overlay { + position: absolute; + height: 100%; + width: 100%; + background-color: rgba($dark-grey, 0.7); + z-index: 999; + top: 0; + left: 0; +} \ No newline at end of file diff --git a/cms/sass/components/_alert.scss b/cms/sass/components/_alert.scss index 2132c103cc..9e84164989 100644 --- a/cms/sass/components/_alert.scss +++ b/cms/sass/components/_alert.scss @@ -13,6 +13,27 @@ cursor: pointer; } + button { + margin-bottom: 0; + } + p { + margin-bottom: 0; + } + + &.focus { + position: relative; + width: 100%; + display: flex; + flex-direction: column; + background-color: $white; + z-index: 1000; + button { + margin-top: 1.5rem; + width: max-content; + align-self: center; + } + } + &--message { background-color: $warm-black; color: $white; diff --git a/portality/static/js/application_form.js b/portality/static/js/application_form.js index 04981952d8..b62581e268 100644 --- a/portality/static/js/application_form.js +++ b/portality/static/js/application_form.js @@ -457,6 +457,12 @@ doaj.af.EditorialApplicationForm = class extends doaj.af.BaseApplicationForm { $(sec).show(); }); + $("#cont_confirmation").click(function() { + $(this).parent().removeClass("focus"); + $(this).hide(); + $("#focus-overlay").hide(); + }) + var that = this; $("#unlock").click(function(event) { event.preventDefault(); diff --git a/portality/templates-v2/management/admin/maned_application.html b/portality/templates-v2/management/admin/maned_application.html index 5400033d90..72fefdcc86 100644 --- a/portality/templates-v2/management/admin/maned_application.html +++ b/portality/templates-v2/management/admin/maned_application.html @@ -14,20 +14,18 @@ {% block body_id %}apply{% endblock %} {% block permanent_warnings %} - {% if obj.application_status == "rejected" and continuation_info.id %} -
-
+ {%- if continuation_info.first_rejection -%} +
+ {%- endif -%} +

This application has been rejected. We found a related older journal record. You may want to withdraw it.
{{ continuation_info.title }}

- + {%- if continuation_info.first_rejection -%} + + {%- endif -%}
-
{% endif %} {% endblock %} From 2b007d98b72cbb06bef499bc1ad766d9043df8b6 Mon Sep 17 00:00:00 2001 From: Aga Date: Fri, 9 Jan 2026 14:05:23 +0000 Subject: [PATCH 03/10] change overlay positioning --- cms/sass/base/_general.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/sass/base/_general.scss b/cms/sass/base/_general.scss index bfbc9e33c7..92ae817cf3 100644 --- a/cms/sass/base/_general.scss +++ b/cms/sass/base/_general.scss @@ -335,7 +335,7 @@ fieldset { } .focus-overlay { - position: absolute; + position: fixed; height: 100%; width: 100%; background-color: rgba($dark-grey, 0.7); From e6e1845ebd059976a9bc2176b67856e789de69b9 Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 13 Jan 2026 12:04:56 +0000 Subject: [PATCH 04/10] clean up the code --- portality/constants.py | 2 ++ portality/core.py | 4 +++- portality/forms/application_processors.py | 5 ++--- .../admin/includes/_warning_continuation.html | 9 +++++++++ .../management/admin/maned_application.html | 14 ++------------ portality/ui/ui_copy.py | 9 +++++++++ portality/view/admin.py | 3 +-- 7 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 portality/templates-v2/management/admin/includes/_warning_continuation.html create mode 100644 portality/ui/ui_copy.py diff --git a/portality/constants.py b/portality/constants.py index a0cd15f521..9128573414 100644 --- a/portality/constants.py +++ b/portality/constants.py @@ -28,6 +28,8 @@ APPLICATION_TYPE_UPDATE_REQUEST = "update_request" APPLICATION_TYPE_NEW_APPLICATION = "new_application" +APP_PROCESSOR_INFO_IS_BEING_REJECTED = "is_being_rejected" + INDEX_RECORD_TYPE_UPDATE_REQUEST_UNFINISHED = "Update Request (in progress)" INDEX_RECORD_TYPE_UPDATE_REQUEST_FINISHED = "Update Request (finished)" INDEX_RECORD_TYPE_NEW_APPLICATION_UNFINISHED = "Application (in progress)" diff --git a/portality/core.py b/portality/core.py index 066e7b65f2..3e415d0832 100644 --- a/portality/core.py +++ b/portality/core.py @@ -14,7 +14,7 @@ from portality.error_handler import setup_error_logging from portality.lib import es_data_mapping, dates, paths from portality.ui.debug_toolbar import DoajDebugToolbar -from portality.ui import templates +from portality.ui import templates, ui_copy import elasticsearch @@ -293,6 +293,8 @@ def setup_jinja(app): app.jinja_env.globals['type'] = type #~~->Constants:Config~~ app.jinja_env.globals['constants'] = constants + app.jinja_env.globals['copy'] = ui_copy + app.jinja_env.globals['render_copy'] = ui_copy.render_copy app.jinja_env.globals['templates'] = templates #~~-> Dates:Library~~ app.jinja_env.globals['dates'] = dates diff --git a/portality/forms/application_processors.py b/portality/forms/application_processors.py index 0ceabd793f..e9a3ae2f59 100644 --- a/portality/forms/application_processors.py +++ b/portality/forms/application_processors.py @@ -394,10 +394,9 @@ def finalise(self, account, save_target=True, email_alert=True): return # is the application is being rejected now? + self.info = None if self.target.application_status == constants.APPLICATION_STATUS_REJECTED and self.source.application_status != constants.APPLICATION_STATUS_REJECTED: - self.info = "is being rejected" - else: - self.info = "gibbirish" + self.info = constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED # if this application is being accepted, then do the conversion to a journal if self.target.application_status == constants.APPLICATION_STATUS_ACCEPTED: diff --git a/portality/templates-v2/management/admin/includes/_warning_continuation.html b/portality/templates-v2/management/admin/includes/_warning_continuation.html new file mode 100644 index 0000000000..55e0577fbc --- /dev/null +++ b/portality/templates-v2/management/admin/includes/_warning_continuation.html @@ -0,0 +1,9 @@ +{%- if continuation_info.first_rejection -%} +
+{%- endif -%} +
+ {{ render_copy(copy.WARNING, url=url_for('admin.journal_page', journal_id=continuation_info.id), title=continuation_info.title) }} + {%- if continuation_info.first_rejection -%} + + {%- endif -%} +
\ No newline at end of file diff --git a/portality/templates-v2/management/admin/maned_application.html b/portality/templates-v2/management/admin/maned_application.html index 72fefdcc86..447fb998c7 100644 --- a/portality/templates-v2/management/admin/maned_application.html +++ b/portality/templates-v2/management/admin/maned_application.html @@ -14,18 +14,8 @@ {% block body_id %}apply{% endblock %} {% block permanent_warnings %} - {% if obj.application_status == "rejected" and continuation_info.id %} - {%- if continuation_info.first_rejection -%} -
- {%- endif -%} -
-

This application has been rejected. We found a related older journal record. You may want to withdraw it.
- {{ continuation_info.title }} -

- {%- if continuation_info.first_rejection -%} - - {%- endif -%} -
+ {% if obj.application_status == constants.APPLICATION_STATUS_REJECTED and continuation_info.id %} + {% include "management/admin/includes/_warning_continuation.html" with context %} {% endif %} {% endblock %} diff --git a/portality/ui/ui_copy.py b/portality/ui/ui_copy.py new file mode 100644 index 0000000000..bc16af43f9 --- /dev/null +++ b/portality/ui/ui_copy.py @@ -0,0 +1,9 @@ +from jinja2 import Template +from markupsafe import Markup + +WARNING = """

This application has been rejected. We found a related older journal record. You may want to withdraw it.
+ {{ title }} +

""" + +def render_copy(template_str, **context): + return Markup(Template(template_str).render(**context)) diff --git a/portality/view/admin.py b/portality/view/admin.py index cfb14d5c65..67db5ffdd5 100644 --- a/portality/view/admin.py +++ b/portality/view/admin.py @@ -448,8 +448,7 @@ def application(application_id, **kwargs): if request.method == "GET": fc.processor(source=ap) - first_rejection = request.args.get("info") == "is being rejected" - continuation_info = {"first_rejection": first_rejection} + continuation_info = {"first_rejection": request.args.get("info") == constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED} replaces = Journal.find_by_issn(ap.bibjson().replaces) if replaces: r = replaces[0] From 879c46d1b824c88f93c2e074b249ccd56255c63b Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 13 Jan 2026 12:53:14 +0000 Subject: [PATCH 05/10] add continuation info to the quick reject point --- portality/view/admin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/portality/view/admin.py b/portality/view/admin.py index 67db5ffdd5..e52596fb7b 100644 --- a/portality/view/admin.py +++ b/portality/view/admin.py @@ -467,7 +467,6 @@ def application(application_id, **kwargs): # for f in processor.form.resettedFields: # text += "
field: {}, invalid value: {}, new value: {}".format(f["name"], f["data"], f["default"]) # flash(text, 'info') - print(processor.info) flash('Application updated.', 'success') for a in processor.alert: flash_with_url(a, "success") @@ -540,7 +539,7 @@ def application_quick_reject(application_id): flash(msg, "success") # redirect the user back to the edit page - return redirect(url_for('.application', application_id=application_id)) + return redirect(url_for('admin.application', application_id=application_id, info=constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED)) @blueprint.route("/admin_site_search", methods=["GET"]) From 4f04760ddb56d9422ac3da80c08bd4ebf3cfd16a Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 13 Jan 2026 14:32:45 +0000 Subject: [PATCH 06/10] add functional tests --- .../new_application_form/maned_form.yml | 48 +++++++++++++ doajtest/testdrive/factory.py | 4 +- doajtest/testdrive/reject.py | 72 +++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 doajtest/testdrive/reject.py diff --git a/doajtest/testbook/new_application_form/maned_form.yml b/doajtest/testbook/new_application_form/maned_form.yml index 23483521db..925707abd2 100644 --- a/doajtest/testbook/new_application_form/maned_form.yml +++ b/doajtest/testbook/new_application_form/maned_form.yml @@ -99,3 +99,51 @@ tests: - step: Attempt to paste the value (use separate editor) results: - Correct value is pasted +- title: Reject application that is a continuation + steps: + - step: go to /testdrive/reject + - step: login as ProfessorFrostfire (you may want to login in an incognito window) + - step: open "Advances in Cold Lava Mechanics" application (it is available on your dashboard) + - step: change status of the application to "Rejected" by setting "Rejected" status in the "Change status" input + - step: save the application + results: + - application is saved + - new warning is displayed with information about an older journal and a link in the "focus" mode + - it is not possible to click anything outside the warning (application form is dimmed) + - it is not possible to Unlock & Close the application form + - button "Got it!" is displayed at the bottom of the warning + - step: click the link in the warning + results: + - Annals of Cryovolcanic Ecology form is opened in a new tab + - step: Unlock & Close the journal form, close the tab, go back to the application form + - step: Click "Got it" button + results: + - the warning is now displayed in the standard way + - the "Got it!" button is hidden + - the rest of the application is active and it's possible to unlock & close it + - step: Unlock & Close + - step: Open this application again (you can navigate to `/admin/application/` or search for the "Advances in Cold Lava Mechanics" in the admin applications search `/admin/applications`) + results: + - the warning about the older journal is displayed at the top of the application + - the application form is active and editable + - it is possible to Unlock & Close the application + - step: Change the status of the application back to "In progress" and save the application (do not close it!) + results: + - the warning about the older journal disappeared + - step: Once the application is saved click "Quick Reject" button + - step: Choose any rejection reason and click "Quick Reject" button + results: + - application is saved + - the warning is displayed at the top with information about an older journal and a link + - it is not possible to click anything outside the warning (application form is dimmed) + - it is not possible to Unlock & Close the application form + - step: click "Got it" + results: + - the warning about the older journal is displayed in the standard way + - the application form is active and editable + - it is possible to Unlock & Close the application + - step: change any information in the form (other than the status) + - step: save the form + results: + - the application is saved correctly + - the warning is still displayed in the standard way \ No newline at end of file diff --git a/doajtest/testdrive/factory.py b/doajtest/testdrive/factory.py index 28149151cf..6bc6e3af61 100644 --- a/doajtest/testdrive/factory.py +++ b/doajtest/testdrive/factory.py @@ -11,8 +11,8 @@ def create_random_str(self, n_char=10): def generate_unique_issn(self): while True: - s = self.create_random_str(n_char=8) - issn = s[:4] + '-' + s[4:] + s = string.digits + issn = ''.join(random.choices(s, k=4)) + '-' + ''.join(random.choices(s, k=4)) if len(models.Journal.find_by_issn(issn)) == 0 : return issn diff --git a/doajtest/testdrive/reject.py b/doajtest/testdrive/reject.py new file mode 100644 index 0000000000..baa66f24b2 --- /dev/null +++ b/doajtest/testdrive/reject.py @@ -0,0 +1,72 @@ +from doajtest.fixtures import ApplicationFixtureFactory, JournalFixtureFactory +from portality import constants +from doajtest.testdrive.factory import TestDrive +from portality import models +from portality.models import EditorGroup + +class Reject(TestDrive): + def setup(self) -> dict: + + un = "ProfessorFrostfire" + pw1 = self.create_random_str() + admin = models.Account.make_account(un + "@example.com", un, un, [constants.ROLE_ADMIN]) + admin.set_password(pw1) + admin.save(blocking=True) + + eg = EditorGroup(**{ + "name": "The Quill & Gavel Club", + "maned": admin.id, + "editor": admin.id, + "associates": [admin.id] + }) + eg.save(blocking=True) + + jsource = JournalFixtureFactory.make_journal_source(True) + jtitle = "Annals of Cryovolcanic Ecology" + journal = models.Journal(**jsource) + journal.set_id(jtitle.replace(" ", "").lower()) + jeissn = self.generate_unique_issn() + peissn = self.generate_unique_issn() + journal.bibjson().eissn = jeissn + journal.bibjson().pissn = peissn + journal.bibjson().title = jtitle + journal.set_editor_group(eg.id) + journal.set_editor(admin.id) + journal.save() + + asource = ApplicationFixtureFactory.make_application_source() + atitle = "Advances in Cold Lava Mechanics" + application = models.Application(**asource) + application.set_id(atitle.replace(" ", "").lower()) + application.bibjson().eissn = self.generate_unique_issn() + application.bibjson().pissn = self.generate_unique_issn() + application.bibjson().title = atitle + application.bibjson().replaces = [jeissn] + application.set_application_status(constants.APPLICATION_STATUS_IN_PROGRESS) + application.set_editor_group(eg.id) + application.set_editor(admin.id) + application.save(blocking=True) + + return { + "admin": { + "username": admin.id, + "password": pw1 + }, + "records": { + "application": {"title": application.bibjson().title, "id": application.id}, + "journal": journal.bibjson().title, + }, + "non_renderable": { + "journal": journal.id, + "application": application.id, + "edgroup": eg.id + } + } + + def teardown(self, params): + models.Account.remove_by_id(params["admin"]["username"]) + eg = EditorGroup.remove_by_id(params["non_renderable"]["edgroup"]) + models.Journal.remove_by_id(params["non_renderable"]["journal"]) + models.Application.remove_by_id(params["non_renderable"]["application"]) + + return {"status": "success"} From 6f6568a5ed09ed317fcc04f417cb05fc29596543 Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 13 Jan 2026 14:38:15 +0000 Subject: [PATCH 07/10] improve functional test --- .../new_application_form/maned_form.yml | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/doajtest/testbook/new_application_form/maned_form.yml b/doajtest/testbook/new_application_form/maned_form.yml index 925707abd2..42c4067d1d 100644 --- a/doajtest/testbook/new_application_form/maned_form.yml +++ b/doajtest/testbook/new_application_form/maned_form.yml @@ -102,48 +102,45 @@ tests: - title: Reject application that is a continuation steps: - step: go to /testdrive/reject - - step: login as ProfessorFrostfire (you may want to login in an incognito window) - - step: open "Advances in Cold Lava Mechanics" application (it is available on your dashboard) - - step: change status of the application to "Rejected" by setting "Rejected" status in the "Change status" input + - step: login as ProfessorFrostfire (you may want to log in using an incognito window) + - step: open "Advances in Cold Lava Mechanics" application (available on your dashboard) + - step: change the status to "Rejected" in the "Change status" input - step: save the application results: - application is saved - - new warning is displayed with information about an older journal and a link in the "focus" mode - - it is not possible to click anything outside the warning (application form is dimmed) - - it is not possible to Unlock & Close the application form - - button "Got it!" is displayed at the bottom of the warning + - a warning appears with information about an older journal and a link in "focus" mode + - the form is dimmed; interactions outside the warning are blocked + - the "Got it!" button is displayed at the bottom - step: click the link in the warning results: - - Annals of Cryovolcanic Ecology form is opened in a new tab - - step: Unlock & Close the journal form, close the tab, go back to the application form - - step: Click "Got it" button + - the "Annals of Cryovolcanic Ecology" form opens in a new tab + - step: Unlock & Close the journal form, close the tab, and return to the application form + - step: click the "Got it" button results: - - the warning is now displayed in the standard way + - the warning is now in standard mode - the "Got it!" button is hidden - - the rest of the application is active and it's possible to unlock & close it + - the application is active and can be unlocked & closed - step: Unlock & Close - - step: Open this application again (you can navigate to `/admin/application/` or search for the "Advances in Cold Lava Mechanics" in the admin applications search `/admin/applications`) + - step: open the application again (navigate to `/admin/application/` or search for "Advances in Cold Lava Mechanics" in `/admin/applications`) results: - - the warning about the older journal is displayed at the top of the application - - the application form is active and editable - - it is possible to Unlock & Close the application - - step: Change the status of the application back to "In progress" and save the application (do not close it!) + - the warning about the older journal is displayed at the top + - the application is active and editable + - it can be unlocked & closed + - step: change the status back to "In progress" and save (do not close) results: - - the warning about the older journal disappeared - - step: Once the application is saved click "Quick Reject" button - - step: Choose any rejection reason and click "Quick Reject" button + - the warning disappears + - step: once saved, click the "Quick Reject" button + - step: choose any rejection reason and click "Quick Reject" results: - application is saved - - the warning is displayed at the top with information about an older journal and a link - - it is not possible to click anything outside the warning (application form is dimmed) - - it is not possible to Unlock & Close the application form + - the warning appears again at the top + - the form is dimmed; interactions outside the warning are blocked - step: click "Got it" results: - - the warning about the older journal is displayed in the standard way - - the application form is active and editable - - it is possible to Unlock & Close the application - - step: change any information in the form (other than the status) - - step: save the form + - the warning returns to standard mode + - the application is active and editable + - it can be unlocked & closed + - step: change any information (except status) and save results: - the application is saved correctly - - the warning is still displayed in the standard way \ No newline at end of file + - the warning remains in standard mode From 23b44479576adef47f7215409971851f3ba1093a Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 26 Feb 2026 14:09:15 +0000 Subject: [PATCH 08/10] various fixes to the testdrive, and a bit of simplification on the implementation --- .../testbook/new_application_form/maned_form.yml | 4 +++- .../{reject.py => reject_with_continuation.py} | 15 ++++++++++----- portality/core.py | 6 +++--- portality/forms/application_processors.py | 9 ++++----- .../admin/includes/_warning_continuation.html | 10 ++++++---- .../management/admin/maned_application.html | 2 +- portality/ui/ui_copy.py | 9 --------- portality/view/admin.py | 11 ++++++----- 8 files changed, 33 insertions(+), 33 deletions(-) rename doajtest/testdrive/{reject.py => reject_with_continuation.py} (84%) delete mode 100644 portality/ui/ui_copy.py diff --git a/doajtest/testbook/new_application_form/maned_form.yml b/doajtest/testbook/new_application_form/maned_form.yml index 42c4067d1d..e7131cded8 100644 --- a/doajtest/testbook/new_application_form/maned_form.yml +++ b/doajtest/testbook/new_application_form/maned_form.yml @@ -59,6 +59,7 @@ tests: - step: Click "Unlock and Close" results: - The page closes, and you are able to return to the search interface + - title: Note features for admin context: role: admin @@ -99,9 +100,10 @@ tests: - step: Attempt to paste the value (use separate editor) results: - Correct value is pasted + - title: Reject application that is a continuation steps: - - step: go to /testdrive/reject + - step: go to /testdrive/reject_with_continuation - step: login as ProfessorFrostfire (you may want to log in using an incognito window) - step: open "Advances in Cold Lava Mechanics" application (available on your dashboard) - step: change the status to "Rejected" in the "Change status" input diff --git a/doajtest/testdrive/reject.py b/doajtest/testdrive/reject_with_continuation.py similarity index 84% rename from doajtest/testdrive/reject.py rename to doajtest/testdrive/reject_with_continuation.py index baa66f24b2..f5e678ed4d 100644 --- a/doajtest/testdrive/reject.py +++ b/doajtest/testdrive/reject_with_continuation.py @@ -4,17 +4,19 @@ from portality import models from portality.models import EditorGroup -class Reject(TestDrive): +class RejectWithContinuation(TestDrive): def setup(self) -> dict: - un = "ProfessorFrostfire" + random_str = self.create_random_str() + + un = "ProfessorFrostfire_" + random_str pw1 = self.create_random_str() admin = models.Account.make_account(un + "@example.com", un, un, [constants.ROLE_ADMIN]) admin.set_password(pw1) admin.save(blocking=True) eg = EditorGroup(**{ - "name": "The Quill & Gavel Club", + "name": "The Quill & Gavel Club " + random_str, "maned": admin.id, "editor": admin.id, "associates": [admin.id] @@ -22,7 +24,7 @@ def setup(self) -> dict: eg.save(blocking=True) jsource = JournalFixtureFactory.make_journal_source(True) - jtitle = "Annals of Cryovolcanic Ecology" + jtitle = "Annals of Cryovolcanic Ecology " + random_str journal = models.Journal(**jsource) journal.set_id(jtitle.replace(" ", "").lower()) jeissn = self.generate_unique_issn() @@ -35,7 +37,7 @@ def setup(self) -> dict: journal.save() asource = ApplicationFixtureFactory.make_application_source() - atitle = "Advances in Cold Lava Mechanics" + atitle = "Advances in Cold Lava Mechanics " + random_str application = models.Application(**asource) application.set_id(atitle.replace(" ", "").lower()) application.bibjson().eissn = self.generate_unique_issn() @@ -45,6 +47,9 @@ def setup(self) -> dict: application.set_application_status(constants.APPLICATION_STATUS_IN_PROGRESS) application.set_editor_group(eg.id) application.set_editor(admin.id) + application.remove_current_journal() + application.remove_related_journal() + del application.bibjson().discontinued_date application.save(blocking=True) return { diff --git a/portality/core.py b/portality/core.py index 34337afc38..729de93313 100644 --- a/portality/core.py +++ b/portality/core.py @@ -14,7 +14,7 @@ from portality.error_handler import setup_error_logging from portality.lib import es_data_mapping, dates, paths from portality.ui.debug_toolbar import DoajDebugToolbar -from portality.ui import templates, ui_copy +from portality.ui import templates import elasticsearch @@ -304,8 +304,8 @@ def setup_jinja(app): app.jinja_env.globals['type'] = type #~~->Constants:Config~~ app.jinja_env.globals['constants'] = constants - app.jinja_env.globals['copy'] = ui_copy - app.jinja_env.globals['render_copy'] = ui_copy.render_copy + # app.jinja_env.globals['copy'] = ui_copy + # app.jinja_env.globals['render_copy'] = ui_copy.render_copy app.jinja_env.globals['templates'] = templates #~~-> Dates:Library~~ app.jinja_env.globals['dates'] = dates diff --git a/portality/forms/application_processors.py b/portality/forms/application_processors.py index b1ac0b6fb5..3ca4935ff4 100644 --- a/portality/forms/application_processors.py +++ b/portality/forms/application_processors.py @@ -418,11 +418,6 @@ def finalise(self, account, save_target=True, email_alert=True): self.add_alert(Messages.FORMS__APPLICATION_PROCESSORS__ADMIN_APPLICATION__FINALISE__COULD_NOT_UNREJECT) return - # is the application is being rejected now? - self.info = None - if self.target.application_status == constants.APPLICATION_STATUS_REJECTED and self.source.application_status != constants.APPLICATION_STATUS_REJECTED: - self.info = constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED - # if this application is being accepted, then do the conversion to a journal if self.target.application_status == constants.APPLICATION_STATUS_ACCEPTED: j = applicationService.accept_application(self.target, account) @@ -465,6 +460,10 @@ def finalise(self, account, save_target=True, email_alert=True): # if the application was instead rejected, carry out the rejection actions elif self.source.application_status != constants.APPLICATION_STATUS_REJECTED and self.target.application_status == constants.APPLICATION_STATUS_REJECTED: + # FIXME: I'm not really sure what `info` is for - it has been defined but unused in the + # base class for ages. This doesn't feel right, though, but since it's unused doesn't + # cause any actual problems right now + self.info = constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED # reject the application applicationService.reject_application(self.target, current_user._get_current_object()) diff --git a/portality/templates-v2/management/admin/includes/_warning_continuation.html b/portality/templates-v2/management/admin/includes/_warning_continuation.html index 55e0577fbc..ba468e4504 100644 --- a/portality/templates-v2/management/admin/includes/_warning_continuation.html +++ b/portality/templates-v2/management/admin/includes/_warning_continuation.html @@ -1,9 +1,11 @@ -{%- if continuation_info.first_rejection -%} +{%- if continuation_info.initial_warning -%}
{%- endif -%} -
- {{ render_copy(copy.WARNING, url=url_for('admin.journal_page', journal_id=continuation_info.id), title=continuation_info.title) }} - {%- if continuation_info.first_rejection -%} +
+

This application has been rejected. We found a related older journal record. You may want to withdraw it.
+ {{ continuation_info.journal.bibjson().title }} +

+ {%- if continuation_info.initial_warning -%} {%- endif -%}
\ No newline at end of file diff --git a/portality/templates-v2/management/admin/maned_application.html b/portality/templates-v2/management/admin/maned_application.html index 447fb998c7..70067b1e5f 100644 --- a/portality/templates-v2/management/admin/maned_application.html +++ b/portality/templates-v2/management/admin/maned_application.html @@ -14,7 +14,7 @@ {% block body_id %}apply{% endblock %} {% block permanent_warnings %} - {% if obj.application_status == constants.APPLICATION_STATUS_REJECTED and continuation_info.id %} + {% if obj.application_status == constants.APPLICATION_STATUS_REJECTED and continuation_info.journal %} {% include "management/admin/includes/_warning_continuation.html" with context %} {% endif %} {% endblock %} diff --git a/portality/ui/ui_copy.py b/portality/ui/ui_copy.py deleted file mode 100644 index bc16af43f9..0000000000 --- a/portality/ui/ui_copy.py +++ /dev/null @@ -1,9 +0,0 @@ -from jinja2 import Template -from markupsafe import Markup - -WARNING = """

This application has been rejected. We found a related older journal record. You may want to withdraw it.
- {{ title }} -

""" - -def render_copy(template_str, **context): - return Markup(Template(template_str).render(**context)) diff --git a/portality/view/admin.py b/portality/view/admin.py index e52596fb7b..bdd5545ed9 100644 --- a/portality/view/admin.py +++ b/portality/view/admin.py @@ -448,14 +448,15 @@ def application(application_id, **kwargs): if request.method == "GET": fc.processor(source=ap) - continuation_info = {"first_rejection": request.args.get("info") == constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED} + continuation_info = {"initial_warning": request.args.get("info") == constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED} replaces = Journal.find_by_issn(ap.bibjson().replaces) if replaces: - r = replaces[0] - continuation_info["id"] = r.id - continuation_info["title"] = r.bibjson().title + continuation_info["journal"] = replaces[0] + # continuation_info["id"] = r.id + # continuation_info["title"] = r.bibjson().title return fc.render_template(obj=ap, lock=lockinfo, form_diff=form_diff, - current_journal=current_journal, lcc_tree=lcc_jstree, autochecks=autochecks, continuation_info=continuation_info) + current_journal=current_journal, lcc_tree=lcc_jstree, autochecks=autochecks, + continuation_info=continuation_info) elif request.method == "POST": processor = fc.processor(formdata=request.form, source=ap) From 6279cccdc0f905c464e00eed9f07c2bb48fa6b07 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 26 Feb 2026 14:10:14 +0000 Subject: [PATCH 09/10] final bit of dead code cleanup --- portality/core.py | 2 -- portality/view/admin.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/portality/core.py b/portality/core.py index 729de93313..125c25426d 100644 --- a/portality/core.py +++ b/portality/core.py @@ -304,8 +304,6 @@ def setup_jinja(app): app.jinja_env.globals['type'] = type #~~->Constants:Config~~ app.jinja_env.globals['constants'] = constants - # app.jinja_env.globals['copy'] = ui_copy - # app.jinja_env.globals['render_copy'] = ui_copy.render_copy app.jinja_env.globals['templates'] = templates #~~-> Dates:Library~~ app.jinja_env.globals['dates'] = dates diff --git a/portality/view/admin.py b/portality/view/admin.py index bdd5545ed9..c1a686d143 100644 --- a/portality/view/admin.py +++ b/portality/view/admin.py @@ -448,12 +448,12 @@ def application(application_id, **kwargs): if request.method == "GET": fc.processor(source=ap) + continuation_info = {"initial_warning": request.args.get("info") == constants.APP_PROCESSOR_INFO_IS_BEING_REJECTED} replaces = Journal.find_by_issn(ap.bibjson().replaces) if replaces: continuation_info["journal"] = replaces[0] - # continuation_info["id"] = r.id - # continuation_info["title"] = r.bibjson().title + return fc.render_template(obj=ap, lock=lockinfo, form_diff=form_diff, current_journal=current_journal, lcc_tree=lcc_jstree, autochecks=autochecks, continuation_info=continuation_info) From 96e7d1ba606410c548996621751f75f83c2d6a2d Mon Sep 17 00:00:00 2001 From: Aga Date: Thu, 26 Mar 2026 13:05:07 +0000 Subject: [PATCH 10/10] fix functional tests --- doajtest/testbook/journal_form/maned_form.yml | 4 ++-- doajtest/testbook/new_application_form/maned_form.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doajtest/testbook/journal_form/maned_form.yml b/doajtest/testbook/journal_form/maned_form.yml index 22a88581d3..a42c6ce8e0 100644 --- a/doajtest/testbook/journal_form/maned_form.yml +++ b/doajtest/testbook/journal_form/maned_form.yml @@ -180,7 +180,7 @@ tests: role: admin steps: - step: Go to admin journal search page at /admin/journals - - step: "Locate a record with the metadata value 'Last full review: Never'" and click "Edit this journal" + - step: 'Locate a record with the metadata value "Last full review: Never" and click "Edit this journal"' - step: Locate the "Last Full Review" section of the form - step: Enter a date in the future in "Last Full Review" field results: @@ -202,7 +202,7 @@ tests: role: admin steps: - step: Go to admin journal search page at /admin/journals - - step: "Locate a record with the metadata value 'Last Owner Transfer: Never'" and click "Edit this journal" + - step: 'Locate a record with the metadata value "Last Owner Transfer: Never" and click "Edit this journal"' - step: Locate the "Re-assign publisher account" section of the form - step: Change the user to a different user account - step: Save the journal record diff --git a/doajtest/testbook/new_application_form/maned_form.yml b/doajtest/testbook/new_application_form/maned_form.yml index e7131cded8..7f31df03d6 100644 --- a/doajtest/testbook/new_application_form/maned_form.yml +++ b/doajtest/testbook/new_application_form/maned_form.yml @@ -50,7 +50,8 @@ tests: subject classifications - step: Remove one subject classification - step: Click "Unlock & Close" - results: Confirmation dialog is displayed warning you about unsaved changes + results: + - Confirmation dialog is displayed warning you about unsaved changes - step: Click "Stay on Page" and then 'Save' results: - The form saves