Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds BS5 modal components #234

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ For a manual install:
'djangocms_frontend.contrib.link',
'djangocms_frontend.contrib.listgroup',
'djangocms_frontend.contrib.media',
'djangocms_frontend.contrib.modal',
'djangocms_frontend.contrib.tabs',
'djangocms_frontend.contrib.utilities',

Expand Down
Empty file.
120 changes: 120 additions & 0 deletions djangocms_frontend/contrib/modal/cms_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
from cms.plugin_pool import plugin_pool
from django.utils.translation import gettext_lazy as _

from ... import settings
from ...cms_plugins import CMSUIPlugin
from ...common import AttributesMixin
from .. import modal
from . import forms, models

mixin_factory = settings.get_renderer(modal)


@plugin_pool.register_plugin
class ModalPlugin(mixin_factory("Modal"), AttributesMixin, CMSUIPlugin):
"""
Component > "Modal" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

name = _("Modal")
module = _("Frontend")
model = models.Modal
form = forms.ModalForm
change_form_template = "djangocms_frontend/admin/modal.html"
allow_children = True
child_classes = [
"ModalTriggerPlugin",
"ModalContainerPlugin",
]

fieldsets = [
(None, {"fields": ("modal_siblings",)}),
]


@plugin_pool.register_plugin
class ModalTriggerPlugin(mixin_factory("ModalTrigger"), AttributesMixin, CMSUIPlugin):
"""
Component > "Modal" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

name = _("Modal trigger")
module = _("Frontend")
model = models.ModalTrigger
form = forms.ModalTriggerForm
allow_children = True
parent_classes = [
"ModalPlugin"
]

fieldsets = [
(None, {"fields": ("trigger_identifier",)}),
]


@plugin_pool.register_plugin
class ModalContainerPlugin(mixin_factory("ModalContainer"), CMSUIPlugin):
"""
Component > "Modal Container" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

name = _("Modal container")
module = _("Frontend")
model = models.ModalContainer
form = forms.ModalContainerForm
allow_children = True
parent_classes = [
"ModalPlugin"
]
child_classes = [
"ModalInnerPlugin",

]
fieldsets = [
(
None,
{
"fields": (
"container_identifier",
("modal_centered"),
("modal_static", "modal_scrollable"),
("modal_size", "modal_fullscreen"),
("modal_footer"),
)
}
),
]


@plugin_pool.register_plugin
class ModalInnerPlugin(
mixin_factory("ModalInner"),
CMSUIPlugin,
):
"""
Component > "Modal Container Content" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""
name = _("Modal inner")
module = _("Frontend")
model = models.ModalInner
form = forms.ModalInnerForm
allow_children = True
parent_classes = [
"ModalContainerPlugin",
]

fieldsets = [
(
None,
{
"fields": (
"inner_type",
"attributes",
)
},
),
]
26 changes: 26 additions & 0 deletions djangocms_frontend/contrib/modal/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.utils.translation import gettext_lazy as _

MODAL_CENTERED_CHOICES = (
("modal-dialog-centered", _("Vertically centered")),
("modal-dialog-centered modal-dialog-scrollable", _("Vertically centered scrollable")),
)

MODAL_SIZE_CHOICES = (
("modal-sm", _("Small")),
("modal-lg", _("Large")),
("modal-xl", _("Extra Large")),
)

MODAL_FULLSCREEN_CHOICES = (
("modal-fullscreen", _("Allways")),
("modal-fullscreen-sm-down", _("Fullscreen below sm")),
("modal-fullscreen-md-down", _("Fullscreen below md")),
("modal-fullscreen-lg-down", _("Fullscreen below lg")),
("modal-fullscreen-xl-down", _("Fullscreen below xl")),
("modal-fullscreen-xxl-down", _("Fullscreen below xxl")),
)

MODAL_INNER_TYPE_CHOICES = (
("modal-body", _("Body")),
("modal-header", _("Header")),
)
174 changes: 174 additions & 0 deletions djangocms_frontend/contrib/modal/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from entangled.forms import EntangledModelForm

from ... import settings
from ...fields import AttributesFormField, ButtonGroup, TagTypeFormField
from ...helpers import first_choice
from ...models import FrontendUIItem
from .. import modal
from .constants import (
MODAL_CENTERED_CHOICES,
MODAL_FULLSCREEN_CHOICES,
MODAL_INNER_TYPE_CHOICES,
MODAL_SIZE_CHOICES,
)

# TODO leaving this comment for now
# data-bs-toggle="modal" data-bs-target="#modalExample"
# aria-expanded="false" aria-controls="modalExample">
# data-bs-target can also be classes
# data-bs-parent links to the wrapper modal
# <div class="modal" id="modalExample">

mixin_factory = settings.get_forms(modal)


class ModalForm(mixin_factory("Modal"), EntangledModelForm):
"""
Component > "Modal" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

class Meta:
model = FrontendUIItem
entangled_fields = {
"config": [
"modal_siblings",
"attributes",
]
}
untangled_fields = ("tag_type",)

modal_siblings = forms.CharField(
label=_("Siblings"),
initial=".card",
required=False,
help_text=_("Element to be used to create a modal."),
)
attributes = AttributesFormField()
tag_type = TagTypeFormField()


class ModalTriggerForm(mixin_factory("ModalTrigger"), EntangledModelForm):
"""
Component > "Modal Trigger" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

class Meta:
model = FrontendUIItem
entangled_fields = {
"config": [
"trigger_identifier",
"attributes",
]
}
untangled_fields = ("tag_type",)

trigger_identifier = forms.SlugField(
label=_("Unique identifier"),
required=True,
help_text=_("Identifier to connect trigger with container."),
)
attributes = AttributesFormField()
tag_type = TagTypeFormField()


class ModalContainerForm(mixin_factory("ModalContainer"), EntangledModelForm):
"""
Component > "Modal Container" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

class Meta:
model = FrontendUIItem
entangled_fields = {
"config": [
"container_identifier",
"attributes",
"modal_centered",
"modal_static",
"modal_footer",
"modal_scrollable",
"modal_size",
"modal_fullscreen",
]
}
untangled_fields = ("tag_type",)

container_identifier = forms.SlugField(
label=_("Unique identifier"),
required=True,
help_text=_("Identifier to connect trigger with container."),
)

modal_centered = forms.ChoiceField(
label=_("Centered"),
choices=settings.EMPTY_CHOICE + MODAL_CENTERED_CHOICES,
required=False,
)

modal_static = forms.BooleanField(
label=_("Static backdrop"),
required=False,
help_text=_("If selected, the modal will not close when clicking outside of it."),
)

modal_footer = forms.BooleanField(
label=_("Footer and close button"),
required=False,
help_text=_("If selected, the modal will show a modal footer with a close button."),
)

modal_scrollable = forms.BooleanField(
label=_("Scrollable"),
required=False,
help_text=_("Enable scrolling in the container."),
)

modal_size = forms.ChoiceField(
label=_("Size"),
choices=settings.EMPTY_CHOICE + MODAL_SIZE_CHOICES,
required=False,
)

modal_fullscreen = forms.ChoiceField(
label=_("Fullscreen"),
choices=settings.EMPTY_CHOICE + MODAL_FULLSCREEN_CHOICES,
required=False,
)

attributes = AttributesFormField()
tag_type = TagTypeFormField()


class ModalInnerForm(mixin_factory("ModalInner"), EntangledModelForm):
"""
Component > "Modal Container Content" Plugin
https://getbootstrap.com/docs/5.0/components/modal/
"""

class Meta:
model = FrontendUIItem
entangled_fields = {
"config": [
"inner_type",
]
}
untangled_fields = ("tag_type",)

inner_type = forms.ChoiceField(
label=_("Type"),
choices=settings.EMPTY_CHOICE + MODAL_INNER_TYPE_CHOICES,
required=True,
)

inner_type = forms.ChoiceField(
label=_("Inner type"),
choices=MODAL_INNER_TYPE_CHOICES,
initial=first_choice(MODAL_INNER_TYPE_CHOICES),
help_text=_("Define the structure of the plugin."),
widget=ButtonGroup(attrs=dict(label_class="btn-secondary")),
)
attributes = AttributesFormField()
Empty file.
21 changes: 21 additions & 0 deletions djangocms_frontend/contrib/modal/frameworks/bootstrap5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class ModalRenderMixin:
render_template = "djangocms_frontend/bootstrap5/modal.html"


class ModalContainerRenderMixin:
render_template = "djangocms_frontend/bootstrap5/modal-container.html"

def render(self, context, instance, placeholder):
return super().render(context, instance, placeholder)


class ModalInnerRenderMixin:
render_template = "djangocms_frontend/bootstrap5/modal-inner.html"

def render(self, context, instance, placeholder):
instance.add_classes(instance.inner_type)
return super().render(context, instance, placeholder)


class ModalTriggerRenderMixin:
render_template = "djangocms_frontend/bootstrap5/modal-trigger.html"
Loading
Loading