Skip to content

Commit

Permalink
Merge pull request #197 from plone/pat-contentbrowser-widget
Browse files Browse the repository at this point in the history
Implement `ContentBrowserWidget` for the new `pat-contentbrowser` pattern
  • Loading branch information
petschki authored Sep 20, 2024
2 parents 8feba93 + bc626b5 commit d38e1fa
Show file tree
Hide file tree
Showing 10 changed files with 539 additions and 63 deletions.
9 changes: 9 additions & 0 deletions news/197.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Implement new `ContentBrowserWidget` for `pat-contentbrowser` pattern.

The deprecated `RelatedItemsWidget` and `pat-relateditems` pattern is still available
and imports should not break. But the default widget and converter adapter registration for
z3c.relationfield is changed to the new widget.

Since `plone.app.relationfield` defines the widget with `plone.autoform` schema
hints nothing changes until the package is updated to the new widget.
[petschki]
31 changes: 23 additions & 8 deletions plone/app/z3cform/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import time
from plone.app.z3cform import utils
from plone.app.z3cform.interfaces import IAjaxSelectWidget
from plone.app.z3cform.interfaces import IContentBrowserWidget
from plone.app.z3cform.interfaces import IDatetimeWidget
from plone.app.z3cform.interfaces import IDateWidget
from plone.app.z3cform.interfaces import ILinkWidget
Expand Down Expand Up @@ -304,9 +305,9 @@ def toFieldValue(self, value):
return collectionType(untokenized_value)


@adapter(IRelation, IRelatedItemsWidget)
class RelationChoiceRelatedItemsWidgetConverter(BaseDataConverter):
"""Data converter for RelationChoice fields using the RelatedItemsWidget."""
@adapter(IRelation, IContentBrowserWidget)
class RelationChoiceContentBrowserWidgetConverter(BaseDataConverter):
"""Data converter for RelationChoice fields using the ContentBrowserWidget."""

def toWidgetValue(self, value):
if not value:
Expand All @@ -328,8 +329,16 @@ def toFieldValue(self, value):
return self.field.missing_value


# BBB
@adapter(IRelation, IRelatedItemsWidget)
class RelationChoiceRelatedItemsWidgetConverter(
RelationChoiceContentBrowserWidgetConverter
):
"""backwards compatibility"""


@adapter(IRelation, ISequenceWidget)
class RelationChoiceSelectWidgetConverter(RelationChoiceRelatedItemsWidgetConverter):
class RelationChoiceSelectWidgetConverter(RelationChoiceContentBrowserWidgetConverter):
"""Data converter for RelationChoice fields using with SequenceWidgets,
which expect sequence values.
"""
Expand All @@ -341,9 +350,9 @@ def toWidgetValue(self, value):
return [IUUID(value)]


@adapter(ICollection, IRelatedItemsWidget)
class RelatedItemsDataConverter(BaseDataConverter):
"""Data converter for ICollection fields using the RelatedItemsWidget."""
@adapter(ICollection, IContentBrowserWidget)
class ContentBrowserDataConverter(BaseDataConverter):
"""Data converter for ICollection fields using the ContentBrowserWidget."""

def toWidgetValue(self, value):
"""Converts from field value to widget.
Expand Down Expand Up @@ -405,8 +414,14 @@ def toFieldValue(self, value):
return collectionType(valueType(v) for v in value)


# BBB
@adapter(ICollection, IRelatedItemsWidget)
class RelatedItemsDataConverter(ContentBrowserDataConverter):
"""backwards compatibility"""


@adapter(IRelationList, ISequenceWidget)
class RelationListSelectWidgetDataConverter(RelatedItemsDataConverter):
class RelationListSelectWidgetDataConverter(ContentBrowserDataConverter):
"""Data converter for RelationChoice fields using with SequenceWidgets,
which expect sequence values.
"""
Expand Down
12 changes: 8 additions & 4 deletions plone/app/z3cform/converters.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@
<adapter factory=".converters.SequenceSelect2WidgetConverter" />
<adapter factory=".converters.AjaxSelectWidgetConverter" />
<adapter factory=".converters.QueryStringDataConverter" />
<adapter factory=".converters.RelationChoiceRelatedItemsWidgetConverter" />
<adapter factory=".converters.RelationChoiceContentBrowserWidgetConverter" />
<adapter
factory=".converters.RelationChoiceRelatedItemsWidgetConverter"
factory=".converters.RelationChoiceContentBrowserWidgetConverter"
for="z3c.relationfield.interfaces.IRelationChoice
.interfaces.ITextWidget"
/>
<adapter factory=".converters.RelationChoiceSelectWidgetConverter" />
<adapter factory=".converters.RelatedItemsDataConverter" />
<adapter factory=".converters.ContentBrowserDataConverter" />
<adapter
factory=".converters.RelatedItemsDataConverter"
factory=".converters.ContentBrowserDataConverter"
for="z3c.relationfield.interfaces.IRelationList
.interfaces.ITextWidget"
/>
<adapter factory=".converters.RelationListSelectWidgetDataConverter" />
<adapter factory=".converters.LinkWidgetDataConverter" />

<!-- BBB -->
<adapter factory=".converters.RelationChoiceRelatedItemsWidgetConverter" />
<adapter factory=".converters.RelatedItemsDataConverter" />
</configure>
4 changes: 4 additions & 0 deletions plone/app/z3cform/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class IRelatedItemsWidget(ITextWidget):
"""Marker interface for the RelatedItemsWidget."""


class IContentBrowserWidget(ITextWidget):
"""Marker interface for the RelatedItemsWidget."""


class IRichTextWidget(patextfield_IRichTextWidget):
"""Marker interface for the TinyMCEWidget."""

Expand Down
44 changes: 44 additions & 0 deletions plone/app/z3cform/templates/contentbrowser_display.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="contentbrowser-widget ${python:normalizeString(view.field.__class__.__name__)}-field"
id="form-widgets-${python:view.__name__}"
tal:define="
plone_view nocall:context/@@plone;
normalizeString python:plone_view.normalizeString;
items python: view.items();
"
tal:condition="items"
i18n:domain="plone"
>
<ul>
<li tal:repeat="item items">
<span title="${item_type}"
tal:define="
item_type python:item.portal_type;
item_type_class python:item.ContentTypeClass();
item_wf_state_class python:item.ReviewStateClass();
appendViewAction python:item.appendViewAction();
item_url python:item.getURL();
item_url python:item_url+'/view' if appendViewAction else item_url;
"
>

<a href="${item_url}">
<img class="mime-icon"
src="${python:item.MimeTypeIcon()}"
tal:condition="python:item_type =='File'"
/>

<span class="${item_type_class} ${item_wf_state_class} url"
tal:content="python:item.Title()"
>
Title
</span>
<span class="discreet"
tal:content="python:item.Description()"
>
Description
</span>
</a>
</span>
</li>
</ul>
</div>
4 changes: 2 additions & 2 deletions plone/app/z3cform/templates/link_input.pt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
<div>
<div class="mb-3 main">
<!-- this gives the name to the "linkType" -->
<input class="pat-relateditems"
<input class="pat-contentbrowser"
name="${view/name}.internal"
type="text"
value="${value}"
data-pat-relateditems="${view/pattern_data}"
data-pat-contentbrowser="${view/pattern_data}"
/>
</div>
</div>
Expand Down
80 changes: 39 additions & 41 deletions plone/app/z3cform/templates/relateditems_display.pt
Original file line number Diff line number Diff line change
@@ -1,46 +1,44 @@
<span class="relateditems-widget ${python:normalizeString(view.field.__class__.__name__)}-field"
id="form-widgets-${python:view.__name__}"
tal:define="
plone_view nocall:context/@@plone;
normalizeString python:plone_view.normalizeString;
items python: view.items();
"
tal:condition="items"
i18n:domain="plone"
<div class="relateditems-widget ${python:normalizeString(view.field.__class__.__name__)}-field"
id="form-widgets-${python:view.__name__}"
tal:define="
plone_view nocall:context/@@plone;
normalizeString python:plone_view.normalizeString;
items python: view.items();
"
tal:condition="items"
i18n:domain="plone"
>
<div>
<ul>
<li tal:repeat="item items">
<span title="${item_type}"
tal:define="
item_type python:item.portal_type;
item_type_class python:item.ContentTypeClass();
item_wf_state_class python:item.ReviewStateClass();
appendViewAction python:item.appendViewAction();
item_url python:item.getURL();
item_url python:item_url+'/view' if appendViewAction else item_url;
"
>
<ul>
<li tal:repeat="item items">
<span title="${item_type}"
tal:define="
item_type python:item.portal_type;
item_type_class python:item.ContentTypeClass();
item_wf_state_class python:item.ReviewStateClass();
appendViewAction python:item.appendViewAction();
item_url python:item.getURL();
item_url python:item_url+'/view' if appendViewAction else item_url;
"
>

<a href="${item_url}">
<img class="mime-icon"
src="${python:item.MimeTypeIcon()}"
tal:condition="python:item_type =='File'"
/>
<a href="${item_url}">
<img class="mime-icon"
src="${python:item.MimeTypeIcon()}"
tal:condition="python:item_type =='File'"
/>

<span class="${item_type_class} ${item_wf_state_class} url"
tal:content="python:item.Title()"
>
<span class="${item_type_class} ${item_wf_state_class} url"
tal:content="python:item.Title()"
>
Title
</span>
<span class="discreet"
tal:content="python:item.Description()"
>
</span>
<span class="discreet"
tal:content="python:item.Description()"
>
Description
</span>
</a>
</span>
</li>
</ul>
</div>
</span>
</span>
</a>
</span>
</li>
</ul>
</div>
Loading

0 comments on commit d38e1fa

Please sign in to comment.