Skip to content

Commit

Permalink
feat: New icon app in contrib including icon picker for wide set of i…
Browse files Browse the repository at this point in the history
…con libraries (#110)

* Upgrade to bootstrap5, add inital icon contrib package

* Optimize css and js

* Fix djlint

* Update readme and changelog

* Update docs

* Add tests

* Update test

* fix flake8

* No coverage of IconPickerWidget

* Update test

* isort tests

* Improve test coverage

* add migration command

* Fix flake8

* Fix: migration of icons

* Fix icon migration

* Dark mode css tweak, docs update, naming typos and spacings for icons

* Improve flake8 and isort friendlyness

* Fix:		Display empty content
  • Loading branch information
fsbraun authored Mar 11, 2023
1 parent a9e9a0b commit 1ea8be5
Show file tree
Hide file tree
Showing 177 changed files with 59,771 additions and 62 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
Changelog
=========

unpublished
===========
1.1.0
=====

* Add djangocms_frontend.contrib.icon
* Fix a bug which lets a carousel not start on django CMS 4.0+
* Update translations
* Add tests for Django 4.2
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ For a manual install:
'djangocms_frontend.contrib.collapse',
'djangocms_frontend.contrib.content',
'djangocms_frontend.contrib.grid',
'djangocms_frontend.contrib.icon',
'djangocms_frontend.contrib.image',
'djangocms_frontend.contrib.jumbotron',
'djangocms_frontend.contrib.link',
Expand Down
2 changes: 1 addition & 1 deletion djangocms_frontend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@
13. Github actions will publish the new package to pypi
"""

__version__ = "1.0.2"
__version__ = "1.1.0"
3 changes: 2 additions & 1 deletion djangocms_frontend/common/bootstrap5/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def render(self, context, instance, placeholder):
if getattr(instance, "background_context", ""):
instance.add_classes(f"bg-{instance.background_context}")
if getattr(instance, "background_opacity", "100") != "100":
instance.add_classes(f"bg-opacity-{instance.background_opacity}")
if instance.background_opacity:
instance.add_classes(f"bg-opacity-{instance.background_opacity}")
if getattr(instance, "background_shadow", ""):
if instance.background_shadow == "reg":
instance.add_classes("shadow")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
1 change: 0 additions & 1 deletion djangocms_frontend/contrib/card/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
11 changes: 9 additions & 2 deletions djangocms_frontend/contrib/carousel/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ class CarouselPlugin(mixin_factory("Carousel"), AttributesMixin, CMSUIPlugin):
("carousel_controls", "carousel_indicators"),
("carousel_keyboard", "carousel_wrap"),
("carousel_ride",),
("carousel_transition", "carousel_pause",),
(
"carousel_transition",
"carousel_pause",
),
)
},
),
Expand All @@ -53,7 +56,11 @@ def get_render_template(self, context, instance, placeholder):

@plugin_pool.register_plugin
class CarouselSlidePlugin(
mixin_factory("CarouselSlide"), AttributesMixin, BackgroundMixin, LinkPluginMixin, CMSUIPlugin
mixin_factory("CarouselSlide"),
AttributesMixin,
BackgroundMixin,
LinkPluginMixin,
CMSUIPlugin,
):
"""
Components > "Carousel Slide" Plugin
Expand Down
9 changes: 5 additions & 4 deletions djangocms_frontend/contrib/carousel/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,7 @@ class Meta:
choices=CAROUSEL_TRANSITION_CHOICES,
required=False,
initial=CAROUSEL_TRANSITION_CHOICES[0][0],
help_text=_(
"Determines if slides change by sliding or fading."
),
help_text=_("Determines if slides change by sliding or fading."),
widget=ButtonGroup(attrs=dict(property="text")),
)
attributes = AttributesFormField(
Expand All @@ -149,7 +147,10 @@ class Meta:


class CarouselSlideForm(
mixin_factory("CarouselSlide"), AbstractLinkForm, BackgroundFormMixin, EntangledModelForm
mixin_factory("CarouselSlide"),
AbstractLinkForm,
BackgroundFormMixin,
EntangledModelForm,
):
"""
Components > "Slide" Plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
1 change: 0 additions & 1 deletion djangocms_frontend/contrib/grid/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
Empty file.
7 changes: 7 additions & 0 deletions djangocms_frontend/contrib/icon/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class IconConfig(AppConfig):
name = "djangocms_frontend.contrib.icon"
verbose_name = _("Icon")
56 changes: 56 additions & 0 deletions djangocms_frontend/contrib/icon/cms_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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 ...common.background import BackgroundMixin
from ...common.responsive import ResponsiveMixin
from ...common.spacing import SpacingMixin
from .. import icon
from . import forms, models

mixin_factory = settings.get_renderer(icon)


class IconPlugin(
mixin_factory("Icon"),
AttributesMixin,
ResponsiveMixin,
SpacingMixin,
BackgroundMixin,
CMSUIPlugin,
):
"""
Universal icon picker
https://github.com/migliori/universal-icon-picker
"""

name = _("Icon")
module = _("Frontend")
model = models.Icon
form = forms.IconForm
text_enabled = True

fieldsets = [
(
None,
{
"fields": (
(
"icon",
"icon_size",
),
"icon_foreground",
"icon_rounded",
)
},
),
]


if "IconPlugin" in plugin_pool.plugins:
# Unregister already installed IconPlugin
del plugin_pool.plugins["IconPlugin"]

plugin_pool.register_plugin(IconPlugin)
60 changes: 60 additions & 0 deletions djangocms_frontend/contrib/icon/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from django.conf import settings
from django.utils.translation import gettext_lazy as _

ICON_CDN = {
"bootstrap-icons": "https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css",
"font-awesome": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css",
"material-icons-filled": "https://fonts.googleapis.com/css2?family=Material+Icons",
"material-icons-outlined": "https://fonts.googleapis.com/css2?family=Material+Icons+Outlined",
"material-icons-round": "https://fonts.googleapis.com/css2?family=Material+Icons+Round",
"material-icons-sharp": "https://fonts.googleapis.com/css2?family=Material+Icons+Sharp",
"material-icons-two-tone": "https://fonts.googleapis.com/css2?family=Material+Icons+Two+Tone",
"fomantic-ui": "fomantic-ui-icons.css",
}

ICON_LIBRARIES_SHOWN = getattr(settings, "DJANGOCMS_FRONTEND_ICONS_LIBRARIES_SHOWN", (
"font-awesome",
"bootstrap-icons",
"material-icons-filled",
"material-icons-outlined",
"material-icons-round",
"material-icons-sharp",
"material-icons-two-tone",
"fomantic-ui",
"foundation-icons",
"elegant-icons",
"feather-icons",
"happy-icons",
"icomoon",
"open-iconic",
"tabler-icons",
"zondicons",
"weather-icons",
))

ICON_LIBRARIES = getattr(
settings,
"DJANGOCMS_FRONTEND_ICON_LIBRARIES",
{
library: (f"{library}.min.json", ICON_CDN.get(library, f"{library}.css"))
for library in getattr(
settings,
"DJANGOCMS_FRONTEND_ICON_LIBRARIES_SHOWN",
ICON_LIBRARIES_SHOWN
)
},
)

ICON_SIZE_CHOICES = getattr(
settings,
"DJANGOCMS_FRONTEND_ICON_SIZE_CHOICES",
(
("", _("Regular")),
("200%", _("x 2")),
("300%", _("x 3")),
("400%", _("x 4")),
("500%", _("x 5")),
("800%", _("x 8")),
("1200%", _("x 12")),
),
)
34 changes: 34 additions & 0 deletions djangocms_frontend/contrib/icon/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import json

from cms.utils.urlutils import static_with_version
from django.forms.fields import JSONField, TextInput

from djangocms_frontend.contrib.icon.conf import ICON_LIBRARIES


class IconPickerWidget(TextInput): # pragma: no cover
class Media:
js = ("djangocms_frontend/icon/vendor/assets/js/universal-icon-picker.min.js",)
css = {"all": (static_with_version("cms/css/cms.icons.css"),)}

template_name = "djangocms_frontend/admin/widgets/icon_picker.html"

def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
try:
json_obj = json.loads(value) or {}
except ValueError:
json_obj = {}
context["widget"]["preview"] = json_obj.get("iconHtml", "")
context["widget"]["library"] = json_obj.get("library", "")
context["icon_libraries"] = [
(key, key.title(), value[0], value[1])
for key, value in ICON_LIBRARIES.items()
]
return context


class IconPickerField(JSONField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", IconPickerWidget)
super().__init__(*args, **kwargs)
60 changes: 60 additions & 0 deletions djangocms_frontend/contrib/icon/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from entangled.forms import EntangledModelForm

from djangocms_frontend.fields import (
AttributesFormField,
ColoredButtonGroup,
TagTypeFormField,
)

from ... import settings
from ...common.background import BackgroundFormMixin
from ...common.responsive import ResponsiveFormMixin
from ...common.spacing import SpacingFormMixin
from ...helpers import first_choice
from ...models import FrontendUIItem
from ...settings import COLOR_STYLE_CHOICES
from .conf import ICON_SIZE_CHOICES
from .fields import IconPickerField


class IconForm(BackgroundFormMixin, ResponsiveFormMixin, SpacingFormMixin, EntangledModelForm):
"""
Layout > "Media" Plugin
http://getbootstrap.com/docs/4.0/layout/media-object/
"""

class Meta:
model = FrontendUIItem
entangled_fields = {
"config": [
"icon",
"icon_size",
"icon_foreground",
"icon_rounded",
"attributes",
]
}
untangled_fields = ("tag_type",)

icon = IconPickerField()
icon_size = forms.ChoiceField(
label=_("Icon size"),
choices=ICON_SIZE_CHOICES,
initial=first_choice(ICON_SIZE_CHOICES),
required=False,
)
icon_foreground = forms.ChoiceField(
label=_("Foreground context"),
choices=settings.EMPTY_CHOICE + COLOR_STYLE_CHOICES,
initial=settings.EMPTY_CHOICE[0][0],
widget=ColoredButtonGroup(),
required=False,
)
icon_rounded = forms.BooleanField(
label=_("Circular icon"),
required=False,
)
attributes = AttributesFormField()
tag_type = TagTypeFormField()
Empty file.
Loading

0 comments on commit 1ea8be5

Please sign in to comment.