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 17 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.
119 changes: 119 additions & 0 deletions djangocms_frontend/contrib/modal/cms_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
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.attributes 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 = [
"CardPlugin"
mavoIn marked this conversation as resolved.
Show resolved Hide resolved
]

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 = [
"CardPlugin"
]
child_classes = [
"ModalInnerPlugin",

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


@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")),
)
167 changes: 167 additions & 0 deletions djangocms_frontend/contrib/modal/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
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_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"),
mavoIn marked this conversation as resolved.
Show resolved Hide resolved
required=False,
help_text=_("Disable scrolling in the container."),
mavoIn marked this conversation as resolved.
Show resolved Hide resolved
)

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"
47 changes: 47 additions & 0 deletions djangocms_frontend/contrib/modal/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Generated by Django 3.2.11 on 2022-01-12 21:03

from django.db import migrations


class Migration(migrations.Migration):
initial = True

dependencies = [
("djangocms_frontend", "0001_initial"),
]

operations = [
migrations.CreateModel(
name="Collapse",
fields=[],
options={
"proxy": True,
"indexes": [],
"constraints": [],
"verbose_name": "Collapse",
},
bases=("djangocms_frontend.frontenduiitem",),
),
migrations.CreateModel(
name="CollapseContainer",
fields=[],
options={
"proxy": True,
"indexes": [],
"constraints": [],
"verbose_name": "Collapse container",
},
bases=("djangocms_frontend.frontenduiitem",),
),
migrations.CreateModel(
name="CollapseTrigger",
fields=[],
options={
"proxy": True,
"indexes": [],
"constraints": [],
"verbose_name": "Collapse trigger",
},
bases=("djangocms_frontend.frontenduiitem",),
),
]
Empty file.
Loading
Loading