Skip to content

Commit

Permalink
Merge branch 'exp_cms4_navbar' into navbar
Browse files Browse the repository at this point in the history
  • Loading branch information
haricot authored Oct 28, 2020
2 parents 76cd22e + 3873118 commit 81aef82
Show file tree
Hide file tree
Showing 20 changed files with 230 additions and 74 deletions.
13 changes: 4 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
dist: focal
language: python

python:
- 3.5
- 3.6
- 3.7
- 3.8

env:
- DJANGOVER=django21 CMSVER=cms36
- DJANGOVER=django22 CMSVER=cms36

- DJANGOVER=django22 CMSVER=cms37
- DJANGOVER=django30 CMSVER=cms37
- DJANGOVER=django22 CMSVER=cms40
- DJANGOVER=django30 CMSVER=cms40

matrix:
allow_failures:
- python: 3.8
env: DJANGOVER=django21 CMSVER=cms36
- python: 3.8
env: DJANGOVER=django22 CMSVER=cms36
- python: 3.8
env: DJANGOVER=django30 CMSVER=cms37

Expand Down
11 changes: 2 additions & 9 deletions cmsplugin_cascade/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
from django.contrib import admin
from django.contrib.sites.shortcuts import get_current_site
from django.forms import Media, widgets
from django.db.models import Q
from django.http import JsonResponse, HttpResponseForbidden, HttpResponseNotFound
from django.urls import reverse
from django.utils.translation import get_language_from_request

from cms.models.pagemodel import Page
from cms.extensions import PageExtensionAdmin
from cms.utils.page import get_page_from_path
from cmsplugin_cascade.utils_helpers import get_page_from_path, get_matching_published_pages
from cmsplugin_cascade.models import CascadePage, IconFont
from cmsplugin_cascade.link.forms import format_page_link

Expand Down Expand Up @@ -79,12 +77,7 @@ def get_published_pagelist(self, request, *args, **kwargs):
return JsonResponse(data)

# otherwise resolve by search term
matching_published_pages = Page.objects.published().public().filter(
Q(title_set__title__icontains=query_term, title_set__language=language)
| Q(title_set__path__icontains=query_term, title_set__language=language)
| Q(title_set__menu_title__icontains=query_term, title_set__language=language)
| Q(title_set__page_title__icontains=query_term, title_set__language=language)
).distinct().order_by('title_set__title').iterator()
matching_published_pages = get_matching_published_pages(query_term,language)

for page in matching_published_pages:
data['results'].append(self.get_result_set(language, page))
Expand Down
44 changes: 25 additions & 19 deletions cmsplugin_cascade/bootstrap4/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
from cmsplugin_cascade import app_settings
from cmsplugin_cascade.bootstrap4.grid import Breakpoint
from cmsplugin_cascade.forms import ManageChildrenFormMixin
from cmsplugin_cascade.utils_helpers import CMS_, get_ancestor
from .plugin_base import BootstrapPluginBase
from . import grid


def get_widget_choices():
breakpoints = app_settings.CMSPLUGIN_CASCADE['bootstrap4']['fluid_bounds']
widget_choices = []
Expand Down Expand Up @@ -104,6 +104,8 @@ def get_css_classes(cls, obj):
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
obj.sanitize_children()
obj.sanitize_related_siblings()


plugin_pool.register_plugin(BootstrapContainerPlugin)

Expand All @@ -127,9 +129,8 @@ class Meta:
class RowGridMixin(object):
def get_grid_instance(self):
row = grid.Bootstrap4Row()
query = Q(plugin_type='BootstrapContainerPlugin') | Q(plugin_type='BootstrapColumnPlugin') \
| Q(plugin_type='BootstrapJumbotronPlugin')
container = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin().get_grid_instance()
class_ancestor_name = ['BootstrapContainerPlugin', 'BootstrapColumnPlugin', 'BootstrapJumbotronPlugin']
container = get_ancestor( class_ancestor_name , plugin=self).get_bound_plugin().get_grid_instance()
container.add_row(row)
return row

Expand Down Expand Up @@ -161,11 +162,11 @@ class ColumnGridMixin(object):
'xs-column-offset', 'sm-column-offset', 'md-column-offset', 'lg-column-offset', 'xs-column-offset']
def get_grid_instance(self):
column = None
query = Q(plugin_type='BootstrapRowPlugin')
row_obj = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin()
row_obj = get_ancestor(['BootstrapRowPlugin'], plugin=self).get_bound_plugin()
# column_siblings = row_obj.get_descendants().order_by('depth').filter(plugin_type='BootstrapColumnPlugin')
row = row_obj.get_grid_instance()
for column_sibling in self.get_siblings():
siblings = self.parent.get_children()
for column_sibling in siblings:
classes = [val for key, val in column_sibling.get_bound_plugin().glossary.items()
if key in self.valid_keys and val]
if column_sibling.pk == self.pk:
Expand Down Expand Up @@ -195,17 +196,17 @@ def choose_help_text(*phrases):
return phrases[1].format(bs4_breakpoints[first].min)
else:
return phrases[2]
if 'parent' in self._cms_initial_attributes:
container=self._cms_initial_attributes['parent'].get_ancestors().order_by('depth').last().get_bound_plugin()
else:
containers=obj.get_ancestors().filter(plugin_type='BootstrapContainerPlugin')
if containers:
container=containers.order_by('depth').last().get_bound_plugin()
else:
jumbotrons=obj.get_ancestors().filter(plugin_type='BootstrapJumbotronPlugin')
container=jumbotrons.order_by('depth').last().get_bound_plugin()
breakpoints = container.glossary['breakpoints']

container = get_ancestor(['BootstrapContainerPlugin','BootstrapJumbotronPlugin'],
_cms_initial_attributes=self._cms_initial_attributes,
plugin=obj
).get_bound_plugin()

if 'breakpoints' in container.glossary:
breakpoints = container.glossary['breakpoints']
elif 'media_queries' in container.glossary:
#Case Jumbotron is first, its not has ancestor container
breakpoints = list(container.glossary['media_queries'].keys())

width_fields, offset_fields, reorder_fields, responsive_fields = {}, {}, {}, {}
units = [ngettext_lazy("{} unit", "{} units", i).format(i) for i in range(0, 13)]
Expand Down Expand Up @@ -334,9 +335,14 @@ class Meta:
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
obj.sanitize_children()
if not CMS_:
obj.sanitize_related_siblings()

def sanitize_related_siblings_model(self):
self.sanitize_related_siblings()

@classmethod
def sanitize_model(cls, obj):
def sanitize_model(cls,obj):
sanitized = super().sanitize_model(obj)
return sanitized

Expand Down
11 changes: 8 additions & 3 deletions cmsplugin_cascade/bootstrap4/secondary_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from django.utils.translation import gettext_lazy as _
from entangled.forms import EntangledModelFormMixin
from cms.plugin_pool import plugin_pool
from cms.models.pagemodel import Page
from cms.models import Page
from cms.sitemaps import CMSSitemap
from cmsplugin_cascade.utils_helpers import CMS_
from .plugin_base import BootstrapPluginBase


class SecondaryMenuFormMixin(EntangledModelFormMixin):
page_id = ChoiceField(
label=_("CMS Page Id"),
Expand All @@ -29,7 +30,11 @@ class Meta:
entangled_fields = {'glossary': ['page_id', 'offset', 'limit']}

def __init__(self, *args, **kwargs):
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
if CMS_:
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
else:
pages_id = [ p.id for p in CMSSitemap().items()]
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False).filter(id__in=pages_id)]
self.base_fields['page_id'].choices = choices
super().__init__(*args, **kwargs)

Expand Down
3 changes: 2 additions & 1 deletion cmsplugin_cascade/link/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from cms.utils import get_current_site
from cms.models import Page
from cmsplugin_cascade.utils_helpers import get_qs_pages_public
from entangled.forms import EntangledModelFormMixin, get_related_object
from filer.models.filemodels import File as FilerFileModel
from filer.fields.file import AdminFileWidget, FilerFileField
Expand Down Expand Up @@ -54,7 +55,7 @@ class LinkSearchField(ModelChoiceField):
widget = PageSelect2Widget()

def __init__(self, *args, **kwargs):
queryset = Page.objects.public()
queryset = get_qs_pages_public()
try:
queryset = queryset.published().on_site(get_current_site())
except:
Expand Down
1 change: 1 addition & 0 deletions cmsplugin_cascade/link/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

33 changes: 28 additions & 5 deletions cmsplugin_cascade/models_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from cms.models import CMSPlugin
from cms.plugin_pool import plugin_pool
from cms.utils.placeholder import get_placeholder_conf

from cmsplugin_cascade.utils_helpers import CMS_

class CascadeModelBase(CMSPlugin):
"""
Expand Down Expand Up @@ -60,9 +60,15 @@ def get_parent_instance(self):
except model.DoesNotExist:
continue
# in case our plugin is the child of a TextPlugin, return its grandparent
parent = self.get_parent()
if CMS_:
parent = self.get_parent()
else:
parent = self.parent
if parent and parent.plugin_type == 'TextPlugin':
grandparent_id = self.get_parent().parent_id
if CMS_:
grandparent_id = self.get_parent().parent_id
else:
grandparent_id = self.parent.parent_id
for model in CascadeModelBase._get_cascade_elements():
try:
return model.objects.get(id=grandparent_id)
Expand Down Expand Up @@ -98,6 +104,17 @@ def get_num_children(self):
"""
return self.get_children().count()

def sanitize_related_siblings(self):
"""
Save relateds siblings depend save_model change inherited CMSPluginBase.
"""
if self.parent:
plugins = self.__class__.objects.filter(id__in=self.parent._get_descendants_ids())
for i in plugins:
if i.plugin_class.require_parent or i.plugin_class.parent_classes:
i.save()
return True

def sanitize_children(self):
"""
Recursively walk down the plugin tree and invoke method ``save(sanitize_only=True)`` for
Expand All @@ -109,7 +126,7 @@ def sanitize_children(self):
for child in children:
child.save(sanitize_only=True)
child.sanitize_children()

@classmethod
def from_db(cls, db, field_names, values):
instance = cls(*values)
Expand All @@ -126,10 +143,15 @@ def save(self, sanitize_only=False, *args, **kwargs):
sanitized = self.plugin_class.sanitize_model(self)
if sanitize_only:
if sanitized:
super().save(no_signals=True)
super().save()
else:
super().save(*args, **kwargs)

def delete(self, *args, **kwargs):
super().delete( *args, **kwargs)
if not CMS_:
self.plugin_class.sanitize_related_siblings_model(self)

@classmethod
def _get_cascade_elements(cls):
"""
Expand All @@ -143,3 +165,4 @@ def _get_cascade_elements(cls):
if issubclass(p.model, cls)])
cls._cached_cascade_elements = cce
return cls._cached_cascade_elements

23 changes: 17 additions & 6 deletions cmsplugin_cascade/plugin_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from cms.plugin_base import CMSPluginBaseMetaclass, CMSPluginBase
from cms.utils.compat.dj import is_installed
from cmsplugin_cascade import app_settings
from cmsplugin_cascade.utils_helpers import get_prev_sibling
from .mixins import CascadePluginMixin
from .models_base import CascadeModelBase
from .models import CascadeElement, SharableCascadeElement
Expand Down Expand Up @@ -272,7 +273,7 @@ def get_identifier(cls, instance):
return SafeText()

@classmethod
def sanitize_model(cls, instance):
def sanitize_model(cls, instance,sanitize_related_sibling=None):
"""
This method is called, before the model is written to the database. It can be overloaded
to sanitize the current models, in case a parent model changed in a way, which might
Expand All @@ -284,6 +285,17 @@ def sanitize_model(cls, instance):
instance.glossary = {}
return False

@classmethod
def sanitize_related_siblings_model(cls, instance):
"""
This method is called, after the model is written to the database. It can be overloaded
to sanitize the current related siblings models, in case a require_parent or parent_classes is in plugin,
which might affect these related siblings plugin.
This method shall return `True`, in case a model change was necessary, otherwise it shall
return `False` to prevent a useless database update.
"""
return False

@classmethod
def get_data_representation(cls, instance):
"""
Expand Down Expand Up @@ -363,11 +375,9 @@ def get_previous_instance(self, obj):
Return the previous plugin instance for the given object.
This differs from `obj.get_prev_sibling()` which returns an unsorted sibling.
"""
ordered_siblings = obj.get_siblings().filter(placeholder=obj.placeholder).order_by('position')
pos = list(ordered_siblings).index(obj.cmsplugin_ptr)
if pos > 0:
prev_sibling = ordered_siblings[pos - 1]
return prev_sibling.get_bound_plugin()
prev_sibling = get_prev_sibling(obj)
if prev_sibling:
return prev_sibling.get_bound_plugin()

def get_next_instance(self, obj):
"""
Expand Down Expand Up @@ -405,3 +415,4 @@ def in_edit_mode(self, request, placeholder):
if edit_mode:
edit_mode = placeholder.has_change_permission(request.user)
return edit_mode

Loading

0 comments on commit 81aef82

Please sign in to comment.