From 5024284d3ba6d70d1e2e78d9d5a3bf5307f0ebf2 Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Fri, 8 Nov 2024 09:48:17 +0100 Subject: [PATCH 1/7] ZO-6370: add image grid module to vivi --- .../article/edit/browser/configure.zcml | 21 ++++++++++++++ .../zeit/content/article/edit/browser/edit.py | 11 ++++++++ .../zeit/content/article/edit/configure.zcml | 11 ++++++++ .../zeit/content/article/edit/image_grid.py | 28 +++++++++++++++++++ .../zeit/content/article/edit/interfaces.py | 18 ++++++++++++ .../content/article/edit/tests/modules.xml | 1 + 6 files changed, 90 insertions(+) create mode 100644 core/src/zeit/content/article/edit/image_grid.py diff --git a/core/src/zeit/content/article/edit/browser/configure.zcml b/core/src/zeit/content/article/edit/browser/configure.zcml index f3125cf720..a2c9f1dab2 100644 --- a/core/src/zeit/content/article/edit/browser/configure.zcml +++ b/core/src/zeit/content/article/edit/browser/configure.zcml @@ -827,4 +827,25 @@ permission="zope.View" /> + + + + + + + diff --git a/core/src/zeit/content/article/edit/browser/edit.py b/core/src/zeit/content/article/edit/browser/edit.py index c98746df03..3983a4988b 100644 --- a/core/src/zeit/content/article/edit/browser/edit.py +++ b/core/src/zeit/content/article/edit/browser/edit.py @@ -575,3 +575,14 @@ class EditAnimation(zeit.cms.browser.manual.FormMixin, zeit.edit.browser.form.In @property def prefix(self): return 'animation.{0}'.format(self.context.__name__) + + +class EditImageGrid(zeit.edit.browser.form.InlineForm): + legend = '' + form_fields = zope.formlib.form.FormFields( + zeit.content.article.edit.interfaces.IImageGrid + ).omit(*list(zeit.edit.interfaces.IBlock)) + + @property + def prefix(self): + return 'image_grid.{0}'.format(self.context.__name__) diff --git a/core/src/zeit/content/article/edit/configure.zcml b/core/src/zeit/content/article/edit/configure.zcml index 53afc662a7..6e2b2f45c7 100644 --- a/core/src/zeit/content/article/edit/configure.zcml +++ b/core/src/zeit/content/article/edit/configure.zcml @@ -462,6 +462,17 @@ /> + + + + + diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_grid.py new file mode 100644 index 0000000000..ab6112b426 --- /dev/null +++ b/core/src/zeit/content/article/edit/image_grid.py @@ -0,0 +1,28 @@ +import grokcore.component as grok + +from zeit.cms.i18n import MessageFactory as _ +import zeit.cms.content.property +import zeit.cms.content.reference +import zeit.content.article.edit.block +import zeit.content.article.edit.interfaces + + +@grok.implementer(zeit.content.article.edit.interfaces.IImageGrid) +class ImageGrid(zeit.content.article.edit.block.Block): + type = 'image_grid' + + show_caption = zeit.cms.content.reference.ReferenceProperty('.', 'show_caption') + images = zeit.cms.content.reference.MultiResource('.image', 'image') + rows = zeit.cms.content.reference.ReferenceProperty('.row', 'rows') + + # first_image = zeit.cms.content.reference.SingleResource('.image[1]', 'image') + # second_image = zeit.cms.content.reference.SingleResource('.image[2]', 'image') + # third_image = zeit.cms.content.reference.SingleResource('.image[3]', 'image') + # first_image = zeit.cms.content.reference.SingleResource('.image-1', 'image') + # second_image = zeit.cms.content.reference.SingleResource('.image-2', 'image') + # third_image = zeit.cms.content.reference.SingleResource('.image-3', 'image') + + +class Factory(zeit.content.article.edit.block.BlockFactory): + produces = ImageGrid + title = _('Image Grid') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index 51685733cb..34c419e079 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -653,3 +653,21 @@ class IIngredientDice(IBlock): """ pass + + +class IImageGrid(IBlock): + show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) + images = zope.schema.Tuple( + title=_('Images'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageSource()), + ) + rows = zope.schema.Tuple( + title=_('Rows'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.TextLine(), + ) diff --git a/core/src/zeit/content/article/edit/tests/modules.xml b/core/src/zeit/content/article/edit/tests/modules.xml index de62ac7594..0efa82e5d1 100644 --- a/core/src/zeit/content/article/edit/tests/modules.xml +++ b/core/src/zeit/content/article/edit/tests/modules.xml @@ -29,4 +29,5 @@ Video Ausgabe ARD Video + Bilder-Grid From 6a56c927dc3fbf89f6fd83ae755510308e4ddd90 Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Tue, 12 Nov 2024 09:48:11 +0100 Subject: [PATCH 2/7] ZO-6370: WIP add rows example --- .../zeit/content/article/edit/image_grid.py | 19 ++++++++++++++++--- .../zeit/content/article/edit/interfaces.py | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_grid.py index ab6112b426..bf63aa20c1 100644 --- a/core/src/zeit/content/article/edit/image_grid.py +++ b/core/src/zeit/content/article/edit/image_grid.py @@ -1,5 +1,7 @@ import grokcore.component as grok +import lxml +from zeit.cms.content.property import ObjectPathAttributeProperty from zeit.cms.i18n import MessageFactory as _ import zeit.cms.content.property import zeit.cms.content.reference @@ -9,11 +11,22 @@ @grok.implementer(zeit.content.article.edit.interfaces.IImageGrid) class ImageGrid(zeit.content.article.edit.block.Block): + def __init__(self, context, xml): + # call base constructor + super(ImageGrid, self).__init__(context, xml) + # set xml object to default template, if it has no body + if not self.xml.xpath('//body'): + self.xml.append(lxml.etree.Element('body')) + type = 'image_grid' - show_caption = zeit.cms.content.reference.ReferenceProperty('.', 'show_caption') - images = zeit.cms.content.reference.MultiResource('.image', 'image') - rows = zeit.cms.content.reference.ReferenceProperty('.row', 'rows') + show_caption = ObjectPathAttributeProperty( + '.', 'show_caption', zeit.content.article.edit.interfaces.IImageGrid['show_caption'] + ) + images = zeit.cms.content.reference.MultiResource('.body.image', 'image') + rows = ObjectPathAttributeProperty( + '.row', 'rows', zeit.content.article.edit.interfaces.IImageGrid['rows'] + ) # first_image = zeit.cms.content.reference.SingleResource('.image[1]', 'image') # second_image = zeit.cms.content.reference.SingleResource('.image[2]', 'image') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index 34c419e079..c36dd036f7 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -662,7 +662,7 @@ class IImageGrid(IBlock): default=(), max_length=3, required=False, - value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageSource()), + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), ) rows = zope.schema.Tuple( title=_('Rows'), From d5b3a6fe257954a63ca6707480aed98cf6e0bf7a Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Tue, 12 Nov 2024 15:17:02 +0100 Subject: [PATCH 3/7] ZO-6370: add size and aspect ratio to image grid --- .../zeit/content/article/edit/image_grid.py | 9 +++-- .../zeit/content/article/edit/interfaces.py | 35 +++++++++++++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_grid.py index bf63aa20c1..842318dcf5 100644 --- a/core/src/zeit/content/article/edit/image_grid.py +++ b/core/src/zeit/content/article/edit/image_grid.py @@ -23,10 +23,13 @@ def __init__(self, context, xml): show_caption = ObjectPathAttributeProperty( '.', 'show_caption', zeit.content.article.edit.interfaces.IImageGrid['show_caption'] ) - images = zeit.cms.content.reference.MultiResource('.body.image', 'image') - rows = ObjectPathAttributeProperty( - '.row', 'rows', zeit.content.article.edit.interfaces.IImageGrid['rows'] + size = ObjectPathAttributeProperty( + '.', 'size', zeit.content.article.edit.interfaces.IImageGrid['size'] + ) + aspect_ration = ObjectPathAttributeProperty( + '.', 'aspect_ration', zeit.content.article.edit.interfaces.IImageGrid['aspect_ration'] ) + images = zeit.cms.content.reference.MultiResource('.body.image', 'image') # first_image = zeit.cms.content.reference.SingleResource('.image[1]', 'image') # second_image = zeit.cms.content.reference.SingleResource('.image[2]', 'image') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index c36dd036f7..376fa5387f 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -655,8 +655,36 @@ class IIngredientDice(IBlock): pass +class ImageGridSizeSource(zeit.cms.content.sources.SimpleDictSource): + values = { + 'small': _('Small'), + 'medium': _('Medium'), + 'large': _('Large'), + } + + +class ImageGridAspectRationSource(zeit.cms.content.sources.SimpleDictSource): + values = { + '2-3': _('2:3'), + '3-2': _('3:2'), + '4-3': _('4:3'), + } + + class IImageGrid(IBlock): show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) + size = zope.schema.Choice( + title=_('Size'), + source=ImageGridSizeSource(), + default='medium', + required=True, + ) + aspect_ration = zope.schema.Choice( + title=_('Aspect ration'), + source=ImageGridAspectRationSource(), + default='2-3', + required=True, + ) images = zope.schema.Tuple( title=_('Images'), default=(), @@ -664,10 +692,3 @@ class IImageGrid(IBlock): required=False, value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), ) - rows = zope.schema.Tuple( - title=_('Rows'), - default=(), - max_length=3, - required=False, - value_type=zope.schema.TextLine(), - ) From a6dd771c27858183e2a74c19b1790be6c6fea26e Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Thu, 14 Nov 2024 15:04:43 +0100 Subject: [PATCH 4/7] ZO-6370: add display mode and variant name --- .../zeit/content/article/edit/image_grid.py | 36 +++++++++++++++++-- .../zeit/content/article/edit/interfaces.py | 20 +++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_grid.py index 842318dcf5..5a0084c579 100644 --- a/core/src/zeit/content/article/edit/image_grid.py +++ b/core/src/zeit/content/article/edit/image_grid.py @@ -3,6 +3,7 @@ from zeit.cms.content.property import ObjectPathAttributeProperty from zeit.cms.i18n import MessageFactory as _ +from zeit.content.article.source import LEGACY_DISPLAY_MODE_SOURCE, LEGACY_VARIANT_NAME_SOURCE import zeit.cms.content.property import zeit.cms.content.reference import zeit.content.article.edit.block @@ -23,14 +24,43 @@ def __init__(self, context, xml): show_caption = ObjectPathAttributeProperty( '.', 'show_caption', zeit.content.article.edit.interfaces.IImageGrid['show_caption'] ) + _display_mode = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'display_mode') + _variant_name = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'variant_name') size = ObjectPathAttributeProperty( '.', 'size', zeit.content.article.edit.interfaces.IImageGrid['size'] ) - aspect_ration = ObjectPathAttributeProperty( - '.', 'aspect_ration', zeit.content.article.edit.interfaces.IImageGrid['aspect_ration'] - ) images = zeit.cms.content.reference.MultiResource('.body.image', 'image') + @property + def display_mode(self): + if self._display_mode is not None: + return self._display_mode + # backward compatibility by mapping old layout to display_mode + layout = self.xml.get('layout', None) + mapping = dict(list(LEGACY_DISPLAY_MODE_SOURCE(self))) + return mapping.get( + layout, zeit.content.article.edit.interfaces.IImage['display_mode'].default + ) + + @display_mode.setter + def display_mode(self, value): + self._display_mode = value + + @property + def variant_name(self): + if self._variant_name is not None: + return self._variant_name + # backward compatibility by mapping old layout to display_mode + layout = self.xml.get('layout', None) + mapping = dict(list(LEGACY_VARIANT_NAME_SOURCE(self))) + return mapping.get( + layout, zeit.content.article.edit.interfaces.IImage['variant_name'].default + ) + + @variant_name.setter + def variant_name(self, value): + self._variant_name = value + # first_image = zeit.cms.content.reference.SingleResource('.image[1]', 'image') # second_image = zeit.cms.content.reference.SingleResource('.image[2]', 'image') # third_image = zeit.cms.content.reference.SingleResource('.image[3]', 'image') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index 376fa5387f..a62926da4a 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -679,12 +679,6 @@ class IImageGrid(IBlock): default='medium', required=True, ) - aspect_ration = zope.schema.Choice( - title=_('Aspect ration'), - source=ImageGridAspectRationSource(), - default='2-3', - required=True, - ) images = zope.schema.Tuple( title=_('Images'), default=(), @@ -692,3 +686,17 @@ class IImageGrid(IBlock): required=False, value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), ) + display_mode = zope.schema.Choice( + title=_('Display Mode'), + source=zeit.content.article.source.IMAGE_DISPLAY_MODE_SOURCE, + default='column-width', + required=False, + ) + + # Currently need default for bw compat. + variant_name = zope.schema.Choice( + title=_('Variant Name'), + source=zeit.content.article.source.IMAGE_VARIANT_NAME_SOURCE, + default='wide', + required=False, + ) From 52fc912b59bf9b5ba8732c88a1f54e451f20db2a Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Thu, 14 Nov 2024 15:06:54 +0100 Subject: [PATCH 5/7] ZO-6370: rename image grid to image row --- .../article/edit/browser/configure.zcml | 12 +++++----- .../zeit/content/article/edit/browser/edit.py | 10 ++++---- .../zeit/content/article/edit/configure.zcml | 6 ++--- .../edit/{image_grid.py => image_row.py} | 17 ++++++------- .../zeit/content/article/edit/interfaces.py | 24 +------------------ .../content/article/edit/tests/modules.xml | 2 +- 6 files changed, 23 insertions(+), 48 deletions(-) rename core/src/zeit/content/article/edit/{image_grid.py => image_row.py} (86%) diff --git a/core/src/zeit/content/article/edit/browser/configure.zcml b/core/src/zeit/content/article/edit/browser/configure.zcml index a2c9f1dab2..eef3c1eb57 100644 --- a/core/src/zeit/content/article/edit/browser/configure.zcml +++ b/core/src/zeit/content/article/edit/browser/configure.zcml @@ -827,24 +827,24 @@ permission="zope.View" /> - + diff --git a/core/src/zeit/content/article/edit/browser/edit.py b/core/src/zeit/content/article/edit/browser/edit.py index 3983a4988b..e8647b6d6e 100644 --- a/core/src/zeit/content/article/edit/browser/edit.py +++ b/core/src/zeit/content/article/edit/browser/edit.py @@ -577,12 +577,12 @@ def prefix(self): return 'animation.{0}'.format(self.context.__name__) -class EditImageGrid(zeit.edit.browser.form.InlineForm): +class EditImageRow(zeit.edit.browser.form.InlineForm): legend = '' - form_fields = zope.formlib.form.FormFields( - zeit.content.article.edit.interfaces.IImageGrid - ).omit(*list(zeit.edit.interfaces.IBlock)) + form_fields = zope.formlib.form.FormFields(zeit.content.article.edit.interfaces.IImageRow).omit( + *list(zeit.edit.interfaces.IBlock) + ) @property def prefix(self): - return 'image_grid.{0}'.format(self.context.__name__) + return 'image_row.{0}'.format(self.context.__name__) diff --git a/core/src/zeit/content/article/edit/configure.zcml b/core/src/zeit/content/article/edit/configure.zcml index 6e2b2f45c7..fcd72e0874 100644 --- a/core/src/zeit/content/article/edit/configure.zcml +++ b/core/src/zeit/content/article/edit/configure.zcml @@ -462,13 +462,13 @@ /> - + diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_row.py similarity index 86% rename from core/src/zeit/content/article/edit/image_grid.py rename to core/src/zeit/content/article/edit/image_row.py index 5a0084c579..1d5899e027 100644 --- a/core/src/zeit/content/article/edit/image_grid.py +++ b/core/src/zeit/content/article/edit/image_row.py @@ -10,25 +10,22 @@ import zeit.content.article.edit.interfaces -@grok.implementer(zeit.content.article.edit.interfaces.IImageGrid) -class ImageGrid(zeit.content.article.edit.block.Block): +@grok.implementer(zeit.content.article.edit.interfaces.IImageRow) +class ImageRow(zeit.content.article.edit.block.Block): def __init__(self, context, xml): # call base constructor - super(ImageGrid, self).__init__(context, xml) + super(ImageRow, self).__init__(context, xml) # set xml object to default template, if it has no body if not self.xml.xpath('//body'): self.xml.append(lxml.etree.Element('body')) - type = 'image_grid' + type = 'image_row' show_caption = ObjectPathAttributeProperty( - '.', 'show_caption', zeit.content.article.edit.interfaces.IImageGrid['show_caption'] + '.', 'show_caption', zeit.content.article.edit.interfaces.IImageRow['show_caption'] ) _display_mode = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'display_mode') _variant_name = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'variant_name') - size = ObjectPathAttributeProperty( - '.', 'size', zeit.content.article.edit.interfaces.IImageGrid['size'] - ) images = zeit.cms.content.reference.MultiResource('.body.image', 'image') @property @@ -70,5 +67,5 @@ def variant_name(self, value): class Factory(zeit.content.article.edit.block.BlockFactory): - produces = ImageGrid - title = _('Image Grid') + produces = ImageRow + title = _('Image Row') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index a62926da4a..7530fbdfef 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -655,30 +655,8 @@ class IIngredientDice(IBlock): pass -class ImageGridSizeSource(zeit.cms.content.sources.SimpleDictSource): - values = { - 'small': _('Small'), - 'medium': _('Medium'), - 'large': _('Large'), - } - - -class ImageGridAspectRationSource(zeit.cms.content.sources.SimpleDictSource): - values = { - '2-3': _('2:3'), - '3-2': _('3:2'), - '4-3': _('4:3'), - } - - -class IImageGrid(IBlock): +class IImageRow(IBlock): show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) - size = zope.schema.Choice( - title=_('Size'), - source=ImageGridSizeSource(), - default='medium', - required=True, - ) images = zope.schema.Tuple( title=_('Images'), default=(), diff --git a/core/src/zeit/content/article/edit/tests/modules.xml b/core/src/zeit/content/article/edit/tests/modules.xml index 0efa82e5d1..77ec7038a7 100644 --- a/core/src/zeit/content/article/edit/tests/modules.xml +++ b/core/src/zeit/content/article/edit/tests/modules.xml @@ -29,5 +29,5 @@ Video Ausgabe ARD Video - Bilder-Grid + Bilderreihe From 16d09ca99becd466947379438253ef0772d4c685 Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Thu, 14 Nov 2024 15:30:17 +0100 Subject: [PATCH 6/7] ZO-6370: add show source --- core/src/zeit/content/article/edit/image_row.py | 3 +++ core/src/zeit/content/article/edit/interfaces.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/zeit/content/article/edit/image_row.py b/core/src/zeit/content/article/edit/image_row.py index 1d5899e027..fd5e1b1174 100644 --- a/core/src/zeit/content/article/edit/image_row.py +++ b/core/src/zeit/content/article/edit/image_row.py @@ -24,6 +24,9 @@ def __init__(self, context, xml): show_caption = ObjectPathAttributeProperty( '.', 'show_caption', zeit.content.article.edit.interfaces.IImageRow['show_caption'] ) + show_source = ObjectPathAttributeProperty( + '.', 'show_source', zeit.content.article.edit.interfaces.IImageRow['show_source'] + ) _display_mode = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'display_mode') _variant_name = zeit.cms.content.property.ObjectPathAttributeProperty('.', 'variant_name') images = zeit.cms.content.reference.MultiResource('.body.image', 'image') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index 7530fbdfef..0e72222956 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -657,6 +657,7 @@ class IIngredientDice(IBlock): class IImageRow(IBlock): show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) + show_source = zope.schema.Bool(title=_('Show source'), required=False, default=True) images = zope.schema.Tuple( title=_('Images'), default=(), @@ -670,7 +671,6 @@ class IImageRow(IBlock): default='column-width', required=False, ) - # Currently need default for bw compat. variant_name = zope.schema.Choice( title=_('Variant Name'), From 36ab536ba1a670d74ef949e0b079572600766011 Mon Sep 17 00:00:00 2001 From: Jannis Jahr Date: Thu, 14 Nov 2024 17:52:52 +0100 Subject: [PATCH 7/7] ZO-6370: add prototype for image grid, not working yet! --- .../article/edit/browser/configure.zcml | 22 +++++ .../zeit/content/article/edit/browser/edit.py | 33 +++++++ .../zeit/content/article/edit/configure.zcml | 11 +++ .../zeit/content/article/edit/image_grid.py | 54 +++++++++++ .../zeit/content/article/edit/interfaces.py | 94 +++++++++++++++++++ .../content/article/edit/tests/modules.xml | 1 + 6 files changed, 215 insertions(+) create mode 100644 core/src/zeit/content/article/edit/image_grid.py diff --git a/core/src/zeit/content/article/edit/browser/configure.zcml b/core/src/zeit/content/article/edit/browser/configure.zcml index eef3c1eb57..2b3c7c163c 100644 --- a/core/src/zeit/content/article/edit/browser/configure.zcml +++ b/core/src/zeit/content/article/edit/browser/configure.zcml @@ -848,4 +848,26 @@ permission="zope.View" /> + + + + + + + + diff --git a/core/src/zeit/content/article/edit/browser/edit.py b/core/src/zeit/content/article/edit/browser/edit.py index e8647b6d6e..711a7680b4 100644 --- a/core/src/zeit/content/article/edit/browser/edit.py +++ b/core/src/zeit/content/article/edit/browser/edit.py @@ -586,3 +586,36 @@ class EditImageRow(zeit.edit.browser.form.InlineForm): @property def prefix(self): return 'image_row.{0}'.format(self.context.__name__) + + +class EditImageGrid(zeit.edit.browser.form.InlineForm): + legend = '' + omitted_fields_prefix = ['images_', 'display_mode_', 'variant_name_'] + form_fields = zope.formlib.form.FormFields( + zeit.content.article.edit.interfaces.IImageGrid + ).omit(*list(zeit.edit.interfaces.IBlock)) + _all_form_fields = form_fields + + @property + def prefix(self): + return 'image_grid.{0}'.format(self.context.__name__) + + def setUpWidgets(self, *args, **kw): + super().setUpWidgets(*args, **kw) + image_groups_lengths = [getattr(self.context, f'images_{i}', 0) for i in range(0, 4)] + print(image_groups_lengths) + first_empty_group = next( + (i for i, item in enumerate(image_groups_lengths) if len(item) == 0), None + ) + print(f'first_empty_group: {first_empty_group}') + # All groups are filled! + if first_empty_group is None: + self.form_fields = self._all_form_fields + return + omitted_fields = [ + f'{prefix}{j}' + for prefix in self.omitted_fields_prefix + for j in range(first_empty_group + 1, 4) + ] + print(omitted_fields) + self.form_fields = self._all_form_fields.omit(*omitted_fields) diff --git a/core/src/zeit/content/article/edit/configure.zcml b/core/src/zeit/content/article/edit/configure.zcml index fcd72e0874..3d159ab4a0 100644 --- a/core/src/zeit/content/article/edit/configure.zcml +++ b/core/src/zeit/content/article/edit/configure.zcml @@ -473,6 +473,17 @@ /> + + + + + diff --git a/core/src/zeit/content/article/edit/image_grid.py b/core/src/zeit/content/article/edit/image_grid.py new file mode 100644 index 0000000000..3e3894ff1b --- /dev/null +++ b/core/src/zeit/content/article/edit/image_grid.py @@ -0,0 +1,54 @@ +import grokcore.component as grok +import lxml + +from zeit.cms.content.property import ObjectPathAttributeProperty +from zeit.cms.i18n import MessageFactory as _ +import zeit.cms.content.property +import zeit.cms.content.reference +import zeit.content.article.edit.block +import zeit.content.article.edit.interfaces + + +@grok.implementer(zeit.content.article.edit.interfaces.IImageGrid) +class ImageGrid(zeit.content.article.edit.block.Block): + type = 'image_grid' + + def __init__(self, context, xml): + # call base constructor + super(ImageGrid, self).__init__(context, xml) + for i in range(4): + if not self.xml.xpath('//group%s' % i): + self.xml.append(lxml.etree.Element('group%s' % i)) + + show_caption = ObjectPathAttributeProperty( + '.', 'show_caption', zeit.content.article.edit.interfaces.IImageRow['show_caption'] + ) + show_source = ObjectPathAttributeProperty( + '.', 'show_source', zeit.content.article.edit.interfaces.IImageRow['show_source'] + ) + + # Images and display properties for first group + images_0 = zeit.cms.content.reference.MultiResource('.group0.image', 'image') + image_0 = zeit.cms.content.property.SingleResource('.image') + display_mode_0 = ObjectPathAttributeProperty('.group0', 'display_mode_0') + variant_name_0 = ObjectPathAttributeProperty('.group0', 'variant_name_0') + + # Images and display properties for second group + images_1 = zeit.cms.content.reference.MultiResource('.group1.image', 'image') + display_mode_1 = ObjectPathAttributeProperty('.group1', 'display_mode_1') + variant_name_1 = ObjectPathAttributeProperty('.group1', 'variant_name_1') + + # Images and display properties for second group + images_2 = zeit.cms.content.reference.MultiResource('.group2.image', 'image') + display_mode_2 = ObjectPathAttributeProperty('.group2', 'display_mode_2') + variant_name_2 = ObjectPathAttributeProperty('.group2', 'variant_name_2') + + # Images and display properties for third group + images_3 = zeit.cms.content.reference.MultiResource('.group3.image', 'image') + display_mode_3 = ObjectPathAttributeProperty('.group3', 'display_mode_3') + variant_name_3 = ObjectPathAttributeProperty('.group3', 'variant_name_3') + + +class Factory(zeit.content.article.edit.block.BlockFactory): + produces = ImageGrid + title = _('Image Grid') diff --git a/core/src/zeit/content/article/edit/interfaces.py b/core/src/zeit/content/article/edit/interfaces.py index 0e72222956..e84fbd8bc1 100644 --- a/core/src/zeit/content/article/edit/interfaces.py +++ b/core/src/zeit/content/article/edit/interfaces.py @@ -655,6 +655,9 @@ class IIngredientDice(IBlock): pass +IMAGE_COUNT = 4 # Define the number of image sets in the image grid + + class IImageRow(IBlock): show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) show_source = zope.schema.Bool(title=_('Show source'), required=False, default=True) @@ -678,3 +681,94 @@ class IImageRow(IBlock): default='wide', required=False, ) + + +class IImageGrid(IBlock): + show_caption = zope.schema.Bool(title=_('Show caption'), required=False, default=True) + show_source = zope.schema.Bool(title=_('Show source'), required=False, default=True) + images_0 = zope.schema.Tuple( + title=_('Images'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), + ) + display_mode_0 = zope.schema.Choice( + title=_('Display Mode'), + source=zeit.content.article.source.IMAGE_DISPLAY_MODE_SOURCE, + default='column-width', + required=False, + ) + image_0 = zope.schema.Choice( + title=_('Image'), + description=_('Drag an image group here'), + required=False, + source=zeit.content.image.interfaces.imageGroupSource, + ) + # Currently need default for bw compat. + variant_name_0 = zope.schema.Choice( + title=_('Variant Name'), + source=zeit.content.article.source.IMAGE_VARIANT_NAME_SOURCE, + default='wide', + required=False, + ) + images_1 = zope.schema.Tuple( + title=_('Images'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), + ) + display_mode_1 = zope.schema.Choice( + title=_('Display Mode'), + source=zeit.content.article.source.IMAGE_DISPLAY_MODE_SOURCE, + default='column-width', + required=False, + ) + # Currently need default for bw compat. + variant_name_1 = zope.schema.Choice( + title=_('Variant Name'), + source=zeit.content.article.source.IMAGE_VARIANT_NAME_SOURCE, + default='wide', + required=False, + ) + images_2 = zope.schema.Tuple( + title=_('Images'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), + ) + display_mode_2 = zope.schema.Choice( + title=_('Display Mode'), + source=zeit.content.article.source.IMAGE_DISPLAY_MODE_SOURCE, + default='column-width', + required=False, + ) + # Currently need default for bw compat. + variant_name_2 = zope.schema.Choice( + title=_('Variant Name'), + source=zeit.content.article.source.IMAGE_VARIANT_NAME_SOURCE, + default='wide', + required=False, + ) + images_3 = zope.schema.Tuple( + title=_('Images'), + default=(), + max_length=3, + required=False, + value_type=zope.schema.Choice(source=zeit.content.image.interfaces.ImageGroupSource()), + ) + display_mode_3 = zope.schema.Choice( + title=_('Display Mode'), + source=zeit.content.article.source.IMAGE_DISPLAY_MODE_SOURCE, + default='column-width', + required=False, + ) + # Currently need default for bw compat. + variant_name_3 = zope.schema.Choice( + title=_('Variant Name'), + source=zeit.content.article.source.IMAGE_VARIANT_NAME_SOURCE, + default='wide', + required=False, + ) diff --git a/core/src/zeit/content/article/edit/tests/modules.xml b/core/src/zeit/content/article/edit/tests/modules.xml index 77ec7038a7..c3dd0c206d 100644 --- a/core/src/zeit/content/article/edit/tests/modules.xml +++ b/core/src/zeit/content/article/edit/tests/modules.xml @@ -30,4 +30,5 @@ Ausgabe ARD Video Bilderreihe + Bilder-Grid