assets: add css classes related to assets on cells (#41995)

This commit is contained in:
Lauréline Guérin 2020-04-24 14:12:28 +02:00
parent e4c329edaf
commit fbda225b1a
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 91 additions and 4 deletions

View File

@ -80,12 +80,16 @@ def get_asset(context, *args, **kwargs):
key = None
if 'cell' in kwargs and 'type' in kwargs:
cell = kwargs['cell']
cell_type = kwargs['type']
try:
if not kwargs['cell'].can_have_assets():
if not cell.can_have_assets():
return None
key = kwargs['cell'].get_asset_slot_key(kwargs['type'])
key = cell.get_asset_slot_key(cell_type)
except AttributeError:
return None
if hasattr(cell, '_assets'):
return cell._assets.get(key)
elif len(args) == 1:
key = args[0]

View File

@ -621,6 +621,29 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
def css_class_names(self):
return ' '.join([self.class_name, self.legacy_class_name, self.extra_css_class])
@property
def asset_css_classes(self):
from combo.apps.assets.models import Asset
if not hasattr(self, '_asset_keys'):
self._asset_keys = self.get_asset_slot_keys()
if not hasattr(self, '_assets'):
self._assets = {a.key: a for a in Asset.objects.filter(key__in=self._asset_keys.keys())}
if not self._asset_keys or not self._assets:
return ''
# add has-asset-<slug> for each asset found
css = sorted(['has-asset-{}'.format(v) for k, v in self._asset_keys.items() if k in self._assets])
# add has-any-asset if at least one asset defined
if self._assets:
css.append('has-any-asset')
# add has-all-assets if all assets are defined
if self._assets.keys() == self._asset_keys.keys():
css.append('has-all-assets')
return ' '.join(css)
def can_have_assets(self):
return self.get_slug_for_asset() and self.get_asset_slot_templates()
@ -643,6 +666,12 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
def get_asset_slot_templates(self):
return settings.COMBO_CELL_ASSET_SLOTS.get(self.get_cell_type_str()) or {}
def get_asset_slot_keys(self):
if not self.can_have_assets():
return {}
slot_templates = self.get_asset_slot_templates()
return {self.get_asset_slot_key(key): key for key in slot_templates.keys()}
def get_asset_slots(self):
if not self.can_have_assets():
return {}

View File

@ -4,7 +4,7 @@
{{ skeleton }}
{% endif %}
{% for cell in cells %}
<div class="cell {{ cell.css_class_names }} {% if cell.slug %}{{cell.slug}}{% endif %} {% if cell|shown_because_admin:request %}shown-because-admin{% endif %}"
<div class="cell {{ cell.css_class_names }} {{ cell.asset_css_classes }}{% if cell.slug %} {{cell.slug}}{% endif %}{% if cell|shown_because_admin:request %} shown-because-admin{% endif %}"
{% if cell.slug and cell.use_slug_as_id %}id="{{ cell.slug }}"{% endif %}
data-ajax-cell-url="{{ site_base }}{% url 'combo-public-ajax-page-cell' page_pk=cell.page_id cell_reference=cell.get_reference %}"
data-ajax-cell-loading-message="{{ cell.loading_message }}"

View File

@ -16,6 +16,7 @@
import json
import re
from itertools import chain
import django
from django.conf import settings
@ -46,6 +47,7 @@ if 'mellon' in settings.INSTALLED_APPS:
else:
get_idps = lambda: []
from combo.apps.assets.models import Asset
from combo.data.models import (CellBase, PostException, Page, Redirect,
ParentContentCell, TextCell, PageSnapshot)
from combo.profile.models import Profile
@ -536,6 +538,14 @@ def publish_page(request, page, status=200, template_name=None):
cells = [x for x in cells if x.is_visible(user=request.user)]
mark_duplicated_slugs(cells)
# load assets
for cell in cells:
cell._asset_keys = cell.get_asset_slot_keys()
asset_keys = list(set(chain(*[c._asset_keys.keys() for c in cells])))
assets = list(Asset.objects.filter(key__in=asset_keys))
for cell in cells:
cell._assets = {a.key: a for a in assets if a.key in cell._asset_keys.keys()}
ctx = {
'check_badges': should_check_badges(),
'page': page,

View File

@ -9,10 +9,11 @@ import os
from django.conf import settings
from django.contrib.auth.models import User, Group
from django.core.files import File
from django.urls import reverse
from django.db import connection
from django.utils.http import quote
from django.utils import six
from django.utils.six import StringIO
from django.utils.six.moves.urllib import parse as urlparse
from django.test import override_settings
from django.test.utils import CaptureQueriesContext
@ -26,6 +27,7 @@ import requests
from combo.wsgi import application
from combo.data.models import (Page, CellBase, TextCell, ParentContentCell,
FeedCell, LinkCell, LinkListCell, ConfigJsonCell, Redirect, JsonCell)
from combo.apps.assets.models import Asset
from combo.apps.family.models import FamilyInfosCell
pytestmark = pytest.mark.django_db
@ -1014,3 +1016,45 @@ def test_missing_trailing_slashes(app):
assert urlparse.urlparse(app.get('/foo', status=301).location).path == '/foo/'
# don't be tricked by double slashes
assert urlparse.urlparse(app.get('//foo', status=301).location).path == '/foo/'
def test_cell_asset_css_classes(settings, app, admin_user):
settings.COMBO_CELL_ASSET_SLOTS = {}
page = Page.objects.create(title='Home', slug='index', template_name='standard')
cell = TextCell.objects.create(page=page, placeholder='content', order=0, slug='foo', text='foo')
# test direct access
assert cell.asset_css_classes == ''
# and test asset preload
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell foo"' in resp.text
settings.COMBO_CELL_ASSET_SLOTS = {'data_textcell': {'picture': {'prefix': 'Picture'}}}
cell = TextCell.objects.get(pk=cell.pk)
assert cell.asset_css_classes == ''
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell foo"' in resp.text
Asset.objects.create(key=cell.get_asset_slot_key('picture'), asset=File(StringIO('test'), 'test.png'))
cell = TextCell.objects.get(pk=cell.pk)
assert cell.asset_css_classes == 'has-asset-picture has-any-asset has-all-assets'
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell has-asset-picture has-any-asset has-all-assets foo"' in resp.text
settings.COMBO_CELL_ASSET_SLOTS = {'data_textcell': {'picture': {'prefix': 'Picture'}, 'foo': {'prefix': 'Foo'}}}
cell = TextCell.objects.get(pk=cell.pk)
assert cell.asset_css_classes == 'has-asset-picture has-any-asset'
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell has-asset-picture has-any-asset foo"' in resp.text
Asset.objects.create(key=cell.get_asset_slot_key('foo'), asset=File(StringIO('test'), 'test.png'))
cell = TextCell.objects.get(pk=cell.pk)
assert cell.asset_css_classes == 'has-asset-foo has-asset-picture has-any-asset has-all-assets'
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell has-asset-foo has-asset-picture has-any-asset has-all-assets foo"' in resp.text
Asset.objects.all().delete()
cell = TextCell.objects.get(pk=cell.pk)
assert cell.asset_css_classes == ''
resp = app.get('/', status=200)
assert 'class="cell text-cell textcell foo"' in resp.text