From 7e64671153db597acbb5f8f11cad67285547a338 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 2 Jul 2024 16:32:03 +0200 Subject: [PATCH 1/4] Add migration --- djangocms_text/cms_plugins.py | 6 +-- djangocms_text/html.py | 12 ++--- .../migrations/0003_auto_20240702_1409.py | 44 +++++++++++++++++++ djangocms_text/widgets.py | 2 +- private/js/cms.linkfield.js | 4 +- 5 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 djangocms_text/migrations/0003_auto_20240702_1409.py diff --git a/djangocms_text/cms_plugins.py b/djangocms_text/cms_plugins.py index 3b4869b8..7ae5cb31 100644 --- a/djangocms_text/cms_plugins.py +++ b/djangocms_text/cms_plugins.py @@ -14,7 +14,7 @@ HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, - HttpResponseRedirect, + HttpResponseRedirect, JsonResponse, ) from django.shortcuts import get_object_or_404 from django.template import RequestContext @@ -545,14 +545,14 @@ def get_available_urls(self, request): "text": " " * (0 if search else len(page_content.page.node.path) // 4 - 1) + page_content.title, "url": page_content.get_absolute_url(), - "value": f"cms.page:{page_content.page.pk}", + "id": f"cms.page:{page_content.page.pk}", "verbose": page_content.title, } for page_content in qs ] } ] } - return HttpResponse(json.dumps(urls)) + return JsonResponse(urls) @classmethod def get_child_plugin_candidates(cls, slot, page): diff --git a/djangocms_text/html.py b/djangocms_text/html.py index 2ceb0ebe..32f8981d 100644 --- a/djangocms_text/html.py +++ b/djangocms_text/html.py @@ -90,7 +90,7 @@ def __call__(self) -> dict[str, Union[dict[str, set[str]], set[str], None]]: def clean_html(data: str, full: bool = False, cleaner: NH3Parser = cms_parser) -> str: """ - Cleans HTML from XSS vulnerabilities using lxml + Cleans HTML from XSS vulnerabilities using nh3 If full is False, only the contents inside will be returned (without the tags). """ @@ -185,9 +185,10 @@ def dynamic_href(elem: Element, obj: models.Model, attr: str) -> None: def dynamic_src(elem: Element, obj: models.Model, attr: str) -> None: """ - This method modifies the provided element by setting the value of the specified attribute based on the provided object. - If the object has a "get_absolute_url" method and it returns a non-empty value, the attribute of the element will be set to the URL returned by the method. - Otherwise, the "data-cms-error" attribute of the XML element will be set to "ref-not-found". + This method modifies the provided element by setting the value of the specified attribute based on the provided + object. If the object has a "get_absolute_url" method, and it returns a non-empty value, the attribute of the + element will be set to the URL returned by the method. Otherwise, the "data-cms-error" attribute of the XML + element will be set to "ref-not-found". :param elem: The XML element to modify. :type elem: Element @@ -217,7 +218,8 @@ def render_dynamic_attributes( Parameters: - dyn_html (str): The HTML content with dynamic attributes - admin_objects (bool) (optional): Flag to indicate whether to fetch data from admin objects (default: False) - - remove_attr (bool) (optional): Flag to indicate whether to remove dynamic attributes from the final HTML (default: True) + - remove_attr (bool) (optional): Flag to indicate whether to remove dynamic attributes from the final HTML + (default: True) Returns: - str: The updated HTML content with dynamic attributes diff --git a/djangocms_text/migrations/0003_auto_20240702_1409.py b/djangocms_text/migrations/0003_auto_20240702_1409.py new file mode 100644 index 00000000..348ac559 --- /dev/null +++ b/djangocms_text/migrations/0003_auto_20240702_1409.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.25 on 2024-07-02 14:09 + +from django.db import migrations, models, ProgrammingError + + +def migrate_text_ckeditor_fields(apps, schema_editor): + class CKEditorText(models.Model): + class Meta: + managed = False + db_table = "djangocms_text_ckeditor_text" + cmsplugin_ptr_id = models.PositiveIntegerField(primary_key=True) + body = models.TextField() + + class Text_Text(models.Model): # Name must not be used elsewhere as model + class Meta: + managed = False + db_table = "djangocms_text_text" + cmsplugin_ptr_id = models.PositiveIntegerField(primary_key=True) + body = models.TextField() + json = models.JSONField(blank=True, null=True) + rte = models.CharField(max_length=16, blank=True) + + try: + existing_texts = Text_Text.objects.all().values_list("cmsplugin_ptr_id", flat=True) + qs = CKEditorText.objects.using(schema_editor.connection.alias).exclude(cmsplugin_ptr_id__in=existing_texts) + except ProgrammingError: + return + Text_Text.objects.using(schema_editor.connection.alias).bulk_create( + Text_Text(body=ckeditor_text.body, rte="text_ckeditor4", cmsplugin_ptr_id=ckeditor_text.cmsplugin_ptr_id) + for ckeditor_text in qs + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_text', '0002_text_json_text_rte'), + ] + + operations = [ + migrations.RunPython( + code=migrate_text_ckeditor_fields, + ) + ] diff --git a/djangocms_text/widgets.py b/djangocms_text/widgets.py index 9c2f67a8..c2913d6e 100644 --- a/djangocms_text/widgets.py +++ b/djangocms_text/widgets.py @@ -72,7 +72,7 @@ def __init__( super().__init__(attrs) - self.installed_plugins = installed_plugins # general + self.installed_plugins = installed_plugins or [] # general self.pk = pk # specific self.placeholder = ( placeholder.pk if isinstance(placeholder, models.Model) else placeholder diff --git a/private/js/cms.linkfield.js b/private/js/cms.linkfield.js index f8aeebde..081ea907 100644 --- a/private/js/cms.linkfield.js +++ b/private/js/cms.linkfield.js @@ -86,9 +86,9 @@ class LinkField { _addResult(result) { const item = document.createElement('div'); item.textContent = result.text; - if (result.value) { + if (result.id) { item.classList.add('cms-linkfield-option'); - item.setAttribute('data-value', result.value); + item.setAttribute('data-value', result.id); item.setAttribute('data-href', result.url); item.setAttribute('data-text', result.verbose); item.addEventListener('click', this.handleSelection.bind(this)); From 65bcf8f63b1dacf8b5a6d56d55c1a2112febebf6 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 2 Jul 2024 16:36:48 +0200 Subject: [PATCH 2/4] Fix exception handling --- .../migrations/0003_auto_20240702_1409.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/djangocms_text/migrations/0003_auto_20240702_1409.py b/djangocms_text/migrations/0003_auto_20240702_1409.py index 348ac559..6ee5c968 100644 --- a/djangocms_text/migrations/0003_auto_20240702_1409.py +++ b/djangocms_text/migrations/0003_auto_20240702_1409.py @@ -1,6 +1,6 @@ # Generated by Django 3.2.25 on 2024-07-02 14:09 -from django.db import migrations, models, ProgrammingError +from django.db import migrations, models, OperationalError def migrate_text_ckeditor_fields(apps, schema_editor): @@ -23,12 +23,14 @@ class Meta: try: existing_texts = Text_Text.objects.all().values_list("cmsplugin_ptr_id", flat=True) qs = CKEditorText.objects.using(schema_editor.connection.alias).exclude(cmsplugin_ptr_id__in=existing_texts) - except ProgrammingError: - return - Text_Text.objects.using(schema_editor.connection.alias).bulk_create( - Text_Text(body=ckeditor_text.body, rte="text_ckeditor4", cmsplugin_ptr_id=ckeditor_text.cmsplugin_ptr_id) - for ckeditor_text in qs - ) + Text_Text.objects.using(schema_editor.connection.alias).bulk_create( + Text_Text(body=ckeditor_text.body, rte="text_ckeditor4", cmsplugin_ptr_id=ckeditor_text.cmsplugin_ptr_id) + for ckeditor_text in qs + ) + except OperationalError as e: + if "no such table" in str(e): + return + raise e class Migration(migrations.Migration): From 04e01cf4df8e2e11e5fbda05882797865774f739 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 2 Jul 2024 16:40:44 +0200 Subject: [PATCH 3/4] Update ruff actions --- .github/workflows/lint.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4bd8966d..0ba883ea 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,6 +17,6 @@ jobs: run: pip install --upgrade ruff - name: Run ruff run: | - ruff djangocms_text - ruff djangocms_text_ckeditor - ruff tests + ruff check djangocms_text + ruff check djangocms_text_ckeditor + ruff check tests From 09a6451b214acaeee837db6bb1b33ffd0b8bc9b3 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Wed, 24 Jul 2024 13:30:21 +0200 Subject: [PATCH 4/4] Fix static issue --- djangocms_text/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_text/widgets.py b/djangocms_text/widgets.py index c2913d6e..ac1de0ff 100644 --- a/djangocms_text/widgets.py +++ b/djangocms_text/widgets.py @@ -35,7 +35,7 @@ class Media: } js = ( static_with_version("cms/js/dist/bundle.admin.base.min.js"), - static("djangocms_text/bundles/bundle.editor.min.js"), + "djangocms_text/bundles/bundle.editor.min.js", *(static(js) for js in rte_config.js), )