# HG changeset patch # User Thierry Florac # Date 1569417073 -7200 # Node ID 5940373ec65cd38dee32428b4e17a754a7dc67d5 # Parent 8242968d86b16bd68853daca053e8c6e1842c2be Added pictogram to milestones diff -r 8242968d86b1 -r 5940373ec65c src/pyams_content/component/paragraph/interfaces/milestone.py --- a/src/pyams_content/component/paragraph/interfaces/milestone.py Wed Sep 25 09:52:05 2019 +0200 +++ b/src/pyams_content/component/paragraph/interfaces/milestone.py Wed Sep 25 15:11:13 2019 +0200 @@ -10,8 +10,6 @@ # FOR A PARTICULAR PURPOSE. # -__docformat__ = 'restructuredtext' - from zope.annotation.interfaces import IAttributeAnnotatable from zope.container.constraints import containers, contains from zope.interface import Attribute, Interface @@ -19,8 +17,12 @@ from pyams_content.component.paragraph import CONTENT_PARAGRAPHS_VOCABULARY, IBaseParagraph from pyams_content.interfaces.container import IOrderedContainer +from pyams_content.reference.pictograms.interfaces import SELECTED_PICTOGRAM_VOCABULARY from pyams_i18n.schema import I18nTextField, I18nTextLineField + +__docformat__ = 'restructuredtext' + from pyams_content import _ @@ -42,9 +44,17 @@ required=True) label = I18nTextField(title=_("Associated label"), - description=_("The way this label will be rendered depends on presentation template"), + description=_("The way this label will be rendered depends on " + "presentation template"), required=False) + pictogram_name = Choice(title=_("Pictogram"), + description=_("Name of the pictogram associated with this milestone"), + required=False, + vocabulary=SELECTED_PICTOGRAM_VOCABULARY) + + pictogram = Attribute("Selected pictogram object") + anchor = Choice(title=_("Anchor"), description=_("Paragraph to which this milestone should lead"), vocabulary=CONTENT_PARAGRAPHS_VOCABULARY, diff -r 8242968d86b1 -r 5940373ec65c src/pyams_content/component/paragraph/milestone.py --- a/src/pyams_content/component/paragraph/milestone.py Wed Sep 25 09:52:05 2019 +0200 +++ b/src/pyams_content/component/paragraph/milestone.py Wed Sep 25 15:11:13 2019 +0200 @@ -10,38 +10,44 @@ # FOR A PARTICULAR PURPOSE. # -__docformat__ = 'restructuredtext' - from persistent import Persistent from pyramid.events import subscriber from zope.container.contained import Contained from zope.container.ordered import OrderedContainer from zope.interface import implementer from zope.lifecycleevent import ObjectModifiedEvent -from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent, IObjectRemovedEvent +from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent, \ + IObjectRemovedEvent from zope.location import locate from zope.location.interfaces import ISublocations from zope.schema.fieldproperty import FieldProperty from zope.traversing.interfaces import ITraversable from pyams_catalog.utils import index_object -from pyams_content.component.paragraph import BaseParagraph, BaseParagraphContentChecker, BaseParagraphFactory -from pyams_content.component.paragraph.interfaces import IParagraphContainer, IParagraphContainerTarget, \ - IParagraphFactory -from pyams_content.component.paragraph.interfaces.milestone import IMilestone, IMilestoneContainer, \ - IMilestoneContainerTarget, IMilestoneParagraph, MILESTONE_CONTAINER_KEY, MILESTONE_PARAGRAPH_NAME, \ - MILESTONE_PARAGRAPH_RENDERERS, MILESTONE_PARAGRAPH_TYPE +from pyams_content.component.paragraph import BaseParagraph, BaseParagraphContentChecker, \ + BaseParagraphFactory +from pyams_content.component.paragraph.interfaces import IParagraphContainer, \ + IParagraphContainerTarget, IParagraphFactory +from pyams_content.component.paragraph.interfaces.milestone import IMilestone, \ + IMilestoneContainer, IMilestoneContainerTarget, IMilestoneParagraph, MILESTONE_CONTAINER_KEY, \ + MILESTONE_PARAGRAPH_NAME, MILESTONE_PARAGRAPH_RENDERERS, MILESTONE_PARAGRAPH_TYPE from pyams_content.features.checker import BaseContentChecker -from pyams_content.features.checker.interfaces import ERROR_VALUE, IContentChecker, MISSING_LANG_VALUE, MISSING_VALUE +from pyams_content.features.checker.interfaces import ERROR_VALUE, IContentChecker, \ + MISSING_LANG_VALUE, MISSING_VALUE from pyams_content.features.renderer import RenderersVocabulary +from pyams_content.reference.pictograms import IPictogramTable from pyams_form.interfaces.form import IFormContextPermissionChecker from pyams_i18n.interfaces import II18n, II18nManager, INegotiator from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter from pyams_utils.factory import factory_config -from pyams_utils.registry import get_current_registry, get_utility, utility_config +from pyams_utils.registry import get_current_registry, get_utility, utility_config, query_utility from pyams_utils.request import check_request from pyams_utils.traversing import get_parent from pyams_utils.vocabulary import vocabulary_config +from pyams_utils.zodb import volatile_property + + +__docformat__ = 'restructuredtext' from pyams_content import _ @@ -57,9 +63,26 @@ visible = FieldProperty(IMilestone['visible']) title = FieldProperty(IMilestone['title']) label = FieldProperty(IMilestone['label']) + _pictogram_name = FieldProperty(IMilestone['pictogram_name']) anchor = FieldProperty(IMilestone['anchor']) @property + def pictogram_name(self): + return self._pictogram_name + + @pictogram_name.setter + def pictogram_name(self, value): + if value != self._pictogram_name: + self._pictogram_name = value + del self.pictogram + + @volatile_property + def pictogram(self): + table = query_utility(IPictogramTable) + if table is not None: + return table.get(self._pictogram_name) + + @property def target(self): container = get_parent(self, IParagraphContainer) if container is not None: diff -r 8242968d86b1 -r 5940373ec65c src/pyams_content/component/paragraph/zmi/milestone.py --- a/src/pyams_content/component/paragraph/zmi/milestone.py Wed Sep 25 09:52:05 2019 +0200 +++ b/src/pyams_content/component/paragraph/zmi/milestone.py Wed Sep 25 15:11:13 2019 +0200 @@ -10,8 +10,6 @@ # FOR A PARTICULAR PURPOSE. # -__docformat__ = 'restructuredtext' - import json from pyramid.decorator import reify @@ -23,15 +21,18 @@ from zope.interface import Interface, implementer from zope.schema.vocabulary import getVocabularyRegistry -from pyams_content.component.paragraph.interfaces import CONTENT_PARAGRAPHS_VOCABULARY, IParagraphContainerTarget +from pyams_content.component.paragraph.interfaces import CONTENT_PARAGRAPHS_VOCABULARY, \ + IParagraphContainerTarget from pyams_content.component.paragraph.interfaces.milestone import IMilestone, IMilestoneContainer, \ IMilestoneContainerTarget, IMilestoneParagraph, MILESTONE_PARAGRAPH_TYPE from pyams_content.component.paragraph.milestone import Milestone, MilestoneParagraph -from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \ - BaseParagraphAddForm, BaseParagraphAddMenu, BaseParagraphPropertiesEditForm, IParagraphInnerEditFormButtons +from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, \ + BaseParagraphAJAXEditForm, BaseParagraphAddForm, BaseParagraphAddMenu, \ + BaseParagraphPropertiesEditForm, IParagraphInnerEditFormButtons from pyams_content.component.paragraph.zmi import IParagraphContainerView from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION +from pyams_content.reference.pictograms.zmi.widget import PictogramSelectFieldWidget from pyams_content.shared.common import IWfSharedContent from pyams_form.form import AJAXAddForm, ajax_config from pyams_form.interfaces.form import IInnerForm, IInnerSubForm @@ -40,11 +41,12 @@ from pyams_i18n.interfaces import II18n from pyams_pagelet.pagelet import pagelet_config from pyams_skin.container import switch_element_visibility -from pyams_skin.event import get_json_switched_table_refresh_event, get_json_table_row_refresh_event, \ - get_json_widget_refresh_event +from pyams_skin.event import get_json_switched_table_refresh_event, \ + get_json_table_row_refresh_event, get_json_widget_refresh_event from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IWidgetTitleViewletManager from pyams_skin.layer import IPyAMSLayer -from pyams_skin.table import BaseTable, I18nColumn, SorterColumn, TrashColumn, VisibilitySwitcherColumn +from pyams_skin.table import BaseTable, I18nColumn, SorterColumn, TrashColumn, \ + VisibilitySwitcherColumn from pyams_skin.viewlet.toolbar import ToolbarAction from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config from pyams_utils.traversing import get_parent @@ -53,6 +55,9 @@ from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm from pyams_zmi.zmi.table import InnerTableView + +__docformat__ = 'restructuredtext' + from pyams_content import _ @@ -64,8 +69,9 @@ """Milestones parent form marker interface""" -@viewlet_config(name='add-milestone-paragraph.menu', context=IParagraphContainerTarget, view=IParagraphContainerView, - layer=IPyAMSLayer, manager=IToolbarAddingMenu, weight=600) +@viewlet_config(name='add-milestone-paragraph.menu', context=IParagraphContainerTarget, + view=IParagraphContainerView, layer=IPyAMSLayer, manager=IToolbarAddingMenu, + weight=600) class MilestoneParagraphAddMenu(BaseParagraphAddMenu): """Milestone paragraph add menu""" @@ -75,9 +81,11 @@ paragraph_type = MILESTONE_PARAGRAPH_TYPE -@pagelet_config(name='add-milestone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, +@pagelet_config(name='add-milestone-paragraph.html', context=IParagraphContainerTarget, + layer=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION) -@ajax_config(name='add-milestone-paragraph.json', context=IParagraphContainerTarget, layer=IPyAMSLayer, +@ajax_config(name='add-milestone-paragraph.json', context=IParagraphContainerTarget, + layer=IPyAMSLayer, base=BaseParagraphAJAXAddForm) class MilestoneParagraphAddForm(BaseParagraphAddForm): """Milestone paragraph add form""" @@ -117,7 +125,8 @@ return output -@adapter_config(context=(IMilestoneParagraph, IPyAMSLayer), provides=IParagraphInnerEditor) +@adapter_config(context=(IMilestoneParagraph, IPyAMSLayer), + provides=IParagraphInnerEditor) @ajax_config(name='inner-properties.json', context=IMilestoneParagraph, layer=IPyAMSLayer, base=BaseParagraphAJAXEditForm) @implementer(IInnerForm, IMilestonesParentForm) @@ -178,7 +187,8 @@ return list(super(MilestonesTable, self).values) -@adapter_config(context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IValues) +@adapter_config(context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IValues) class MilestonesTableValuesAdapter(ContextRequestViewAdapter): """Milestones table values adapter""" @@ -187,13 +197,16 @@ return IMilestoneContainer(self.context).values() -@adapter_config(name='sorter', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) +@adapter_config(name='sorter', + context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IColumn) class MilestonesTableSorterColumn(ProtectedFormObjectMixin, SorterColumn): """Milestones table sorter column""" -@view_config(name='set-milestones-order.json', context=IMilestoneContainer, request_type=IPyAMSLayer, - permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) +@view_config(name='set-milestones-order.json', context=IMilestoneContainer, + request_type=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION, + renderer='json', xhr=True) def set_milestones_order(request): """Update milestones order""" order = list(map(str, json.loads(request.params.get('names')))) @@ -201,20 +214,24 @@ return {'status': 'success'} -@adapter_config(name='show-hide', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), +@adapter_config(name='show-hide', + context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) class MilestonesTableShowHideColumn(ProtectedFormObjectMixin, VisibilitySwitcherColumn): """Milestones container visibility switcher column""" -@view_config(name='switch-milestone-visibility.json', context=IMilestoneContainer, request_type=IPyAMSLayer, - permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) +@view_config(name='switch-milestone-visibility.json', context=IMilestoneContainer, + request_type=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION, + renderer='json', xhr=True) def switch_milestone_visibility(request): """Set milestone visibility""" return switch_element_visibility(request, IMilestoneContainer) -@adapter_config(name='name', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) +@adapter_config(name='name', + context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IColumn) class MilestonesTableNameColumn(I18nColumn, I18nAttrColumn): """Milestones table name column""" @@ -226,7 +243,9 @@ return super(MilestonesTableNameColumn, self).getValue(obj) or '--' -@adapter_config(name='info', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) +@adapter_config(name='info', + context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IColumn) class MilestonesTableInfoColumn(I18nColumn, I18nAttrColumn): """Milestones table information column""" @@ -238,7 +257,8 @@ return super(MilestonesTableInfoColumn, self).getValue(obj) or '--' -@adapter_config(name='anchor', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) +@adapter_config(name='anchor', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IColumn) class MilestonesTableAnchorColumn(I18nColumn, GetAttrColumn): """Milestones table anchor column""" @@ -260,12 +280,14 @@ return self.request.localizer.translate(_("(missing paragraph)")).format(obj.anchor) -@adapter_config(name='trash', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), provides=IColumn) +@adapter_config(name='trash', context=(IMilestoneContainerTarget, IPyAMSLayer, MilestonesTable), + provides=IColumn) class MilestonesTableTrashColumn(ProtectedFormObjectMixin, TrashColumn): """Milestones table trash column""" -@adapter_config(name='milestones', context=(IMilestoneContainerTarget, IPyAMSLayer, IMilestonesParentForm), +@adapter_config(name='milestones', + context=(IMilestoneContainerTarget, IPyAMSLayer, IMilestonesParentForm), provides=IInnerSubForm) @implementer(IMilestonesView) class MilestonesView(InnerTableView): @@ -281,8 +303,9 @@ # Milestones forms # -@viewlet_config(name='add-milestone.action', context=IMilestoneContainerTarget, layer=IPyAMSLayer, view=IMilestonesView, - manager=IWidgetTitleViewletManager, permission=MANAGE_CONTENT_PERMISSION, weight=1) +@viewlet_config(name='add-milestone.action', context=IMilestoneContainerTarget, layer=IPyAMSLayer, + view=IMilestonesView, manager=IWidgetTitleViewletManager, + permission=MANAGE_CONTENT_PERMISSION, weight=1) class MilestoneAddAction(ToolbarAction): """Milestone add action""" @@ -303,6 +326,8 @@ icon_css_class = 'fa fa-fw fa-arrow-h' fields = field.Fields(IMilestone).omit('__parent__', '__name__', 'visible') + fields['pictogram_name'].widgetFactory = PictogramSelectFieldWidget + edit_permission = MANAGE_CONTENT_PERMISSION def updateWidgets(self, prefix=None): @@ -320,11 +345,13 @@ return { 'status': 'success', 'message': self.request.localizer.translate(_("Milestone was correctly added")), - 'events': [get_json_switched_table_refresh_event(self.context, self.request, MilestonesTable)] + 'events': [ + get_json_switched_table_refresh_event(self.context, self.request, MilestonesTable)] } -@pagelet_config(name='properties.html', context=IMilestone, layer=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION) +@pagelet_config(name='properties.html', context=IMilestone, layer=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION) @ajax_config(name='properties.json', context=IMilestone, layer=IPyAMSLayer) class MilestonePropertiesEditForm(AdminDialogEditForm): """Milestone properties edit form""" @@ -335,6 +362,8 @@ icon_css_class = 'fa fa-fw fa-arrows-h' fields = field.Fields(IMilestone).omit('__parent__', '__name__', 'visible') + fields['pictogram_name'].widgetFactory = PictogramSelectFieldWidget + edit_permission = MANAGE_CONTENT_PERMISSION def updateWidgets(self, prefix=None): @@ -346,6 +375,7 @@ output = super(self.__class__, self).get_ajax_output(changes) if changes: target = get_parent(self.context, IMilestoneContainerTarget) - output.setdefault('events', []).append(get_json_table_row_refresh_event(target, self.request, - MilestonesTable, self.context)) + output.setdefault('events', []).append( + get_json_table_row_refresh_event(target, self.request, + MilestonesTable, self.context)) return output