diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml
new file mode 100644
index 00000000..0776261d
--- /dev/null
+++ b/.github/workflows/publish-to-live-pypi.yml
@@ -0,0 +1,41 @@
+name: Publish Python 🐍 distributions 📦 to pypi
+
+on:
+ release:
+ types:
+ - published
+
+jobs:
+ build-n-publish:
+ name: Build and publish Python 🐍 distributions 📦 to pypi
+ runs-on: ubuntu-latest
+ environment:
+ name: pypi
+ url: https://pypi.org/p/djangocms-moderation
+ permissions:
+ id-token: write
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python 3.10
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.10'
+
+ - name: Install pypa/build
+ run: >-
+ python -m
+ pip install
+ build
+ --user
+ - name: Build a binary wheel and a source tarball
+ run: >-
+ python -m
+ build
+ --sdist
+ --wheel
+ --outdir dist/
+ .
+
+ - name: Publish distribution 📦 to PyPI
+ if: startsWith(github.ref, 'refs/tags')
+ uses: pypa/gh-action-pypi-publish@release/v1
diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml
new file mode 100644
index 00000000..ae0fd790
--- /dev/null
+++ b/.github/workflows/publish-to-test-pypi.yml
@@ -0,0 +1,43 @@
+name: Publish Python 🐍 distributions 📦 to TestPyPI
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ build-n-publish:
+ name: Build and publish Python 🐍 distributions 📦 to TestPyPI
+ runs-on: ubuntu-latest
+ environment:
+ name: test
+ url: https://test.pypi.org/p/djangocms-moderation
+ permissions:
+ id-token: write
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python 3.10
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.10'
+
+ - name: Install pypa/build
+ run: >-
+ python -m
+ pip install
+ build
+ --user
+ - name: Build a binary wheel and a source tarball
+ run: >-
+ python -m
+ build
+ --sdist
+ --wheel
+ --outdir dist/
+ .
+
+ - name: Publish distribution 📦 to Test PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ repository-url: https://test.pypi.org/legacy/
+ skip_existing: true
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 606c3c76..c489abb2 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -42,4 +42,4 @@ jobs:
run: coverage run ./tests/settings.py
- name: Upload Coverage to Codecov
- uses: codecov/codecov-action@v4
+ uses: codecov/codecov-action@v5
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 59db67e9..e99f5e66 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -9,19 +9,19 @@ ci:
repos:
- repo: https://github.com/asottile/pyupgrade
- rev: v3.16.0
+ rev: v3.19.0
hooks:
- id: pyupgrade
args: ["--py310-plus"]
- repo: https://github.com/adamchainz/django-upgrade
- rev: '1.19.0'
+ rev: '1.22.1'
hooks:
- id: django-upgrade
args: [--target-version, "4.0"]
- repo: https://github.com/PyCQA/flake8
- rev: 7.1.0
+ rev: 7.1.1
hooks:
- id: flake8
@@ -31,7 +31,7 @@ repos:
- id: yesqa
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
+ rev: v5.0.0
hooks:
- id: check-merge-conflict
- id: debug-statements
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f1e63062..1d7eabb0 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -4,6 +4,10 @@ Changelog
Unreleased
==========
+fix: Add data-popup attr to a tag in burger menu item
+fix: Replace SortableAdminMixin by SortableAdminBase for WorkflowAdmin
+fix: Restore "In Collection" button in the toolbar
+fix: Update README.rst and add overview of settings
2.2.1 (2024-07-02)
==================
diff --git a/README.rst b/README.rst
index e2d425b2..93572458 100644
--- a/README.rst
+++ b/README.rst
@@ -23,8 +23,8 @@ Run::
Add the following to your project's ``INSTALLED_APPS``:
- - ``'djangocms_moderation'``
- - ``'adminsortable2'``
+- ``'djangocms_moderation'``
+- ``'adminsortable2'``
Run::
@@ -32,6 +32,69 @@ Run::
to perform the application's database migrations.
+Configuration
+=============
+
+The following settings can be added to your project's settings file to configure django CMS Moderation's behavior:
+
+.. list-table::
+ :header-rows: 1
+ :widths: 50 50
+
+ * - Setting
+ - Description
+ * - ``CMS_MODERATION_DEFAULT_COMPLIANCE_NUMBER_BACKEND``
+ - Default backend class for generating compliance numbers.
+ Default is ``djangocms_moderation.backends.uuid4_backend``.
+ * - ``CMS_MODERATION_COMPLIANCE_NUMBER_BACKENDS``
+ - List of available compliance number backend classes.
+ By default, three backends are configured: ``uuid4_backend``,
+ ``sequential_number_backend``, and
+ ``sequential_number_with_identifier_prefix_backend``.
+ * - ``CMS_MODERATION_ENABLE_WORKFLOW_OVERRIDE``
+ - Enable/disable workflow override functionality. Defaults to ``False``.
+ * - ``CMS_MODERATION_DEFAULT_CONFIRMATION_PAGE_TEMPLATE``
+ - Default template for confirmation pages. Defaults to
+ ``djangocms_moderation/moderation_confirmation.html``
+ * - ``CMS_MODERATION_CONFIRMATION_PAGE_TEMPLATES``
+ - List of available confirmation page templates. Only includes the
+ default template by default.
+ * - ``CMS_MODERATION_COLLECTION_COMMENTS_ENABLED``
+ - Enable/disable comments on collections. Defaults to ``True``.
+ * - ``CMS_MODERATION_REQUEST_COMMENTS_ENABLED``
+ - Enable/disable comments on requests. Defaults to ``True``.
+ * - ``CMS_MODERATION_COLLECTION_NAME_LENGTH_LIMIT``
+ - Maximum length for collection names. Defaults to ``24``.
+ * - ``EMAIL_NOTIFICATIONS_FAIL_SILENTLY``
+ - Control email notification error handling. Defaults to ``False``.
+
+Example Configuration
+---------------------
+
+Add these settings to your project's settings file:
+
+.. code-block:: python
+
+ # Custom compliance number backend
+ CMS_MODERATION_DEFAULT_COMPLIANCE_NUMBER_BACKEND = 'myapp.backends.CustomComplianceNumberBackend'
+
+ # Enable workflow override
+ CMS_MODERATION_ENABLE_WORKFLOW_OVERRIDE = True
+
+ # Custom confirmation template
+ CMS_MODERATION_DEFAULT_CONFIRMATION_PAGE_TEMPLATE = 'custom_confirmation.html'
+
+ # Enable comments
+ CMS_MODERATION_COLLECTION_COMMENTS_ENABLED = True
+ CMS_MODERATION_REQUEST_COMMENTS_ENABLED = True
+
+ # Set collection name length limit
+ CMS_MODERATION_COLLECTION_NAME_LENGTH_LIMIT = 100
+
+ # Control email notification errors
+ EMAIL_NOTIFICATIONS_FAIL_SILENTLY = False
+
+=============
Documentation
=============
diff --git a/djangocms_moderation/cms_toolbars.py b/djangocms_moderation/cms_toolbars.py
index 7679807a..a99a7b66 100644
--- a/djangocms_moderation/cms_toolbars.py
+++ b/djangocms_moderation/cms_toolbars.py
@@ -54,7 +54,7 @@ def _add_moderation_buttons(self):
if not helpers.is_registered_for_moderation(self.toolbar.obj):
return
- if self._is_versioned() and self.toolbar.edit_mode_active:
+ if self._is_versioned() and (self.toolbar.edit_mode_active or self.toolbar.preview_mode_active):
moderation_request = helpers.get_active_moderation_request(self.toolbar.obj)
if moderation_request:
title, url = helpers.get_moderation_button_title_and_url(
diff --git a/djangocms_moderation/monkeypatch.py b/djangocms_moderation/monkeypatch.py
index a439850e..a1ad0f06 100644
--- a/djangocms_moderation/monkeypatch.py
+++ b/djangocms_moderation/monkeypatch.py
@@ -120,6 +120,17 @@ def inner(self, obj, request):
return inner
+def _check_registered_for_moderation(message):
+ """
+ Fail check if object is registered for moderation
+ """
+ def inner(version, user):
+ if is_registered_for_moderation(version.content):
+ raise ConditionFailed(message)
+
+ return inner
+
+
admin.VersionAdmin._get_publish_link = _get_publish_link(
admin.VersionAdmin._get_publish_link
)
@@ -152,5 +163,8 @@ def inner(self, obj, request):
_("Cannot edit a version in an active moderation collection")
)
]
+models.Version.check_publish += [
+ _check_registered_for_moderation(_("Content cannot be published directly. Use the moderation process."))
+]
fields.PlaceholderRelationField.default_checks += [_is_placeholder_review_unlocked]
diff --git a/djangocms_moderation/static/djangocms_moderation/js/burger.js b/djangocms_moderation/static/djangocms_moderation/js/burger.js
index 3fbcdf9e..93efd262 100644
--- a/djangocms_moderation/static/djangocms_moderation/js/burger.js
+++ b/djangocms_moderation/static/djangocms_moderation/js/burger.js
@@ -147,6 +147,7 @@
let li_anchor = document.createElement('a');
const itemId = $(item).attr('id');
const itemTarget = $(item).attr('target');
+ const itemDataPopup = $(item).attr('data-popup');
li_anchor.setAttribute('class', 'cms-actions-dropdown-menu-item-anchor');
li_anchor.setAttribute('href', $(item).attr('href'));
@@ -158,6 +159,10 @@
if (itemTarget !== undefined) {
li_anchor.setAttribute('target', itemTarget);
}
+ // Copy the data-popup attribute if it is set
+ if (itemDataPopup !== undefined) {
+ li_anchor.setAttribute('data-popup', itemDataPopup);
+ }
if ($(item).hasClass('cms-form-get-method')) {
// Ensure the fake-form selector is propagated to the new anchor
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 1e5785d8..f8a8a421 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -118,7 +118,7 @@ tabulate==0.9.0
# via docstrfmt
toml==0.10.2
# via docstrfmt
-tornado==6.4.1
+tornado==6.4.2
# via livereload
typing-extensions==4.9.0
# via
diff --git a/package-lock.json b/package-lock.json
index 0af53185..e8609650 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2179,9 +2179,9 @@
"dev": true
},
"elliptic": {
- "version": "6.5.7",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
- "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
+ "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
"dev": true,
"requires": {
"bn.js": "^4.11.9",
diff --git a/tests/test_admin.py b/tests/test_admin.py
index 32dbd321..2c44b403 100644
--- a/tests/test_admin.py
+++ b/tests/test_admin.py
@@ -440,3 +440,11 @@ def test_workflow_admin_renders_correctly(self):
# django-admin-sortable2 injected its inputs
self.assertContains(result, '')
self.assertContains(result, '