diff --git a/README.rst b/README.rst index 1fc5ac3e..ff929a91 100644 --- a/README.rst +++ b/README.rst @@ -115,7 +115,7 @@ For a manual install: - run ``pip install djangocms-frontend`` -- add the following entries to your ``INSTALLED_APPS``: +- add the following entries to your ``INSTALLED_APPS`` (or only those you need): .. code:: @@ -127,6 +127,7 @@ For a manual install: 'djangocms_frontend.contrib.card', 'djangocms_frontend.contrib.carousel', 'djangocms_frontend.contrib.collapse', + 'djangocms_frontend.contrib.component', 'djangocms_frontend.contrib.content', 'djangocms_frontend.contrib.grid', 'djangocms_frontend.contrib.icon', diff --git a/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse-container.html b/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse-container.html index b0bfcd1b..a1bfc345 100644 --- a/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse-container.html +++ b/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse-container.html @@ -2,7 +2,7 @@ <{{ instance.tag_type }}{{ instance.get_attributes }} id="{{ instance.container_identifier }}" role="tabpanel" - data-bs-parent="#parent-{{ parent.pk|safe }}" + data-bs-parent="#{{ parent.uuid }}" aria-labelledby="trigger-{{ instance.container_identifier }}"> {% for plugin in instance.child_plugin_instances %} {% with forloop as parentloop %}{% render_plugin plugin %}{% endwith %} diff --git a/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse.html b/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse.html index ef270c8c..5907f2d2 100644 --- a/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse.html +++ b/djangocms_frontend/contrib/collapse/templates/djangocms_frontend/bootstrap5/collapse.html @@ -1,6 +1,6 @@ {% load cms_tags frontend %} <{{ instance.tag_type }}{{ instance.get_attributes }} -id="parent-{{ instance.pk|safe }}" +id="{{ instance.uuid }}" data-bs-children="{{ instance.collapse_siblings }}" role="tablist" > diff --git a/djangocms_frontend/contrib/content/cms_plugins.py b/djangocms_frontend/contrib/content/cms_plugins.py index a43c73d7..6af780a3 100644 --- a/djangocms_frontend/contrib/content/cms_plugins.py +++ b/djangocms_frontend/contrib/content/cms_plugins.py @@ -77,6 +77,8 @@ class BlockquotePlugin( ), ] + frontend_editable_fields = ("quote_content", "quote_origin") + @plugin_pool.register_plugin class FigurePlugin( @@ -110,3 +112,5 @@ class FigurePlugin( }, ), ] + + frontend_editable_fields = ("figure_caption",) diff --git a/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/blockquote.html b/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/blockquote.html index 64cf1b24..8509e8f0 100644 --- a/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/blockquote.html +++ b/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/blockquote.html @@ -9,13 +9,13 @@ {# djlint:on #} {% for plugin in instance.child_plugin_instances %} {% with parentloop=forloop parent=instance %}{% render_plugin plugin %}{% endwith %} - {% empty %}{{ instance.quote_content|html_safe }}{% endfor %} + {% empty %}{% inline_field instance "quote_content" "" "html_safe" %}{% endfor %} {# djlint:off #} {# djlint:on #} {% if instance.quote_origin %} {% endif %} diff --git a/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/figure.html b/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/figure.html index b3d90933..363ba055 100644 --- a/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/figure.html +++ b/djangocms_frontend/contrib/content/templates/djangocms_frontend/bootstrap5/figure.html @@ -3,5 +3,5 @@ {% for plugin in instance.child_plugin_instances %} {% with forloop=parentloop parent=instance %}{% render_plugin plugin %}{% endwith %} {% endfor %} -
{{ instance.figure_caption|safe_caption }}
+
{% inline_field instance "figure_caption" "" "safe_caption" %}
diff --git a/docs/source/custom_components.rst b/docs/source/custom_components.rst index 984b9987..9ce61fb9 100644 --- a/docs/source/custom_components.rst +++ b/docs/source/custom_components.rst @@ -4,6 +4,8 @@ Custom Components ################# +.. versionadded:: 2.0 + Some frontend developers prefer custom components specifically tailored to give the project a unique and distinct look. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 3bce1c70..183e0ff6 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -51,6 +51,7 @@ Add the following entries to your ``INSTALLED_APPS``: "djangocms_frontend.contrib.card", "djangocms_frontend.contrib.carousel", "djangocms_frontend.contrib.collapse", + "djangocms_frontend.contrib.component", "djangocms_frontend.contrib.content", "djangocms_frontend.contrib.grid", "djangocms_frontend.contrib.icon", @@ -62,12 +63,6 @@ Add the following entries to your ``INSTALLED_APPS``: "djangocms_frontend.contrib.tabs", "djangocms_frontend.contrib.utilities", -.. note :: Using Django 2.2 to 3.1 - - You will need to add ``django-jsonfield-backport`` to your - ``requirements.txt`` and add ``"django_jsonfield_backport"`` to your - ``INSTALLED_APPS``. - Create necessary database table =============================== @@ -440,15 +435,19 @@ the upper right corner: Using frontend plugins as components in templates ================================================= +.. versionadded:: 2.0 + The plugins of **djangocms-frontend** can be used as components in your templates - even in apps that do not use or integrate with djanog CMS otherwise. This is useful if you want use exactly the same markup for, say, buttons, links, the grid both in pages managed with django CMS and in -other parts of your project. +other parts of your project without duplicating HTML code. -This allows you to keep one set of templates for your django CMS frontend -plugins and any changes to those templates will be reflected in all parts -of your project. +This feature introduces a simple and flexible way to re-use djangocms-frontend +plugins directly in templates without needing to create database entries for +them. This allows developers to maintain clean, reusable, and dynamic +components, such as buttons, cards, links, and more, while minimizing code +repetition. To use a frontend plugin in a template you need to load the ``frontend`` tags and then use the ``plugin`` template tag to render a frontend plugin. @@ -464,15 +463,48 @@ The plugins will be rendered based on their standard attribute settings. You can override these settings by passing them as keyword arguments to the ``plugin`` template tag. -See the documentation of the djanog CMS plugins for examples of how to use -the ``{% plugin %}`` template tag with each plugin. +You can also create more complex reusable components, like a card with inner +elements such as headers, bodies, and lists, by nesting plugins. Here’s an +example of a card component:: + + {% load frontend %} + {% plugin "card" card_alignment="center" card_outline="info" card_text_color="primary" card_full_height=True %} + {% plugin "cardinner" inner_type="card-header" text_alignment="start" %} +

Card title

+ {% endplugin %} + {% plugin "cardinner" inner_type="card-body" text_alignment="center" %} + Some quick example text to build on the card title and make up the bulk of the card's content. + {% endplugin %} + {% plugin "listgroupitem" %}An item{% endplugin %} + {% plugin "listgroupitem" %}A second item{% endplugin %} + {% plugin "listgroupitem" %}A third item{% endplugin %} + {% endplugin %} + +Breakdown of the Code: + +* ``plugin "card"``: Creates the outer card component. + * ``card_alignment="center"``: Aligns the card content to the center. + * ``card_outline="info"``: Gives the card an "info" outline style. + * ``card_text_color="primary"``: Changes the text color to "primary." + * ``card_full_height=True``: Ensures the card takes up the full height of its container. +* Nested ``plugin "cardinner"``: Creates inner components within the card. + * ``inner_type="card-header"``: Specifies a header section for the card. + * ``text_alignment="start"``: Aligns the header text to the start (left). +* Additional nested ``plugin "cardinner"`` and ``listgroupitem``: +* These create the body of the card and a list group inside the card. + +The above template generates a dynamic card component with a header, a body, +and a list group that can be reused across multiple pages without requiring +database entries. + +For more examples, see the documentation of the djanog CMS plugins on of how to +use the ``{% plugin %}`` template tag with each plugin. + .. note:: While this is designed for **djangocms-frontend** plugins primarily, it - will work with most django CMS plugins. + will work with many other django CMS plugins. Since no plugins are created in the database, plugins relying on their instances being available in the database will potentially not work. - This especially is true for plugins that have a foreign key to - other models. diff --git a/docs/source/grid.rst b/docs/source/grid.rst index 1e217be2..c493c7d0 100644 --- a/docs/source/grid.rst +++ b/docs/source/grid.rst @@ -37,6 +37,27 @@ Full container New feature: Containers can have a background color ("context"), opacity and shadow. +Component example +================= + +To create a container in a Django template, you need to load the `frontend` tags +and then use the `plugin` template tag to render the container plugin. +Below is an example of how you might do this:: + + {% load frontend %} + + + {% plugin "container" container_type="container-fluid" %} + {% plugin "row" %} + {% plugin "column" xs_col=6 %} +

This is the first column inside the container.

+ {% endplugin %} + {% plugin "column" xs_col=6 %} +

This is the second column inside the container.

+ {% endplugin %} + {% endplugin %} + {% endplugin %} + .. index:: single: Row