Added actions buttons widgets
authorThierry Florac <thierry.florac@onf.fr>
Fri, 18 May 2018 15:55:15 +0200
changeset 104 659ab1e14dca
parent 103 d06578da5e84
child 105 2a73976299b3
Added actions buttons widgets
src/pyams_form/interfaces/form.py
src/pyams_form/schema.py
src/pyams_form/widget/__init__.py
src/pyams_form/widget/templates/action-display.pt
src/pyams_form/widget/templates/action-input.pt
--- a/src/pyams_form/interfaces/form.py	Fri May 18 15:54:52 2018 +0200
+++ b/src/pyams_form/interfaces/form.py	Fri May 18 15:55:15 2018 +0200
@@ -19,7 +19,7 @@
 from pyams_viewlet.interfaces import IViewletManager
 from pyramid.interfaces import IView
 from z3c.form.interfaces import INPUT_MODE, ISubForm, IWidget, IFormLayer as IBaseFormLayer, ISubmitWidget, \
-    ITextWidget, ITextAreaWidget, ISelectWidget
+    ITextWidget, ITextAreaWidget, ISelectWidget, IButtonWidget
 from zope.interface.interfaces import IObjectEvent, ObjectEvent
 from zope.lifecycleevent.interfaces import IObjectCreatedEvent, IObjectModifiedEvent
 
@@ -62,7 +62,7 @@
     """Base form interface"""
 
 
-@template_config(template='../templates/form.pt', layer=IFormLayer)
+@template_config(template='templates/form.pt', layer=IFormLayer)
 class IForm(IBaseForm):
     """Default form interface"""
 
@@ -292,7 +292,7 @@
 # Inner form interfaces
 #
 
-@template_config(template='../templates/inner-form.pt', layer=IFormLayer)
+@template_config(template='templates/inner-form.pt', layer=IFormLayer)
 class IInnerForm(IForm):
     """Inner form marker interface"""
 
@@ -300,7 +300,7 @@
                          schema=IForm)
 
 
-@template_config(template='../templates/widget-form.pt', layer=IFormLayer)
+@template_config(template='templates/widget-form.pt', layer=IFormLayer)
 class IWidgetForm(IForm):
     """Widget form marker interface"""
 
@@ -496,6 +496,28 @@
     """Close button widget interface"""
 
 
+class IActionWidget(IButtonWidget):
+    """Action button widget interface"""
+
+    label_css_class = TextLine(title="Label icon CSS class",
+                               description="CSS class associated with label",
+                               required=True,
+                               default='fa fa-fw fa-edit')
+
+    click_handler = TextLine(title="Button click handler",
+                             description="Javascript function called by button click",
+                             required=False)
+
+    url = TextLine(title="Button target URL",
+                   description="Target URL accessed by button click",
+                   required=False)
+
+    modal_target = Bool(title="Modal target?",
+                        description="If True, target URL is opened in a modal frame",
+                        required=False,
+                        default=False)
+
+
 class IDateWidget(ITextWidget):
     """Date widget interface"""
 
--- a/src/pyams_form/schema.py	Fri May 18 15:54:52 2018 +0200
+++ b/src/pyams_form/schema.py	Fri May 18 15:55:15 2018 +0200
@@ -21,6 +21,8 @@
 # import packages
 from z3c.form.button import Button
 from zope.interface import implementer
+from zope.schema import TextLine, Bool
+from zope.schema.fieldproperty import FieldProperty
 
 
 class IResetButton(IButton):
@@ -39,3 +41,47 @@
 @implementer(ICloseButton)
 class CloseButton(Button):
     """Close button"""
+
+
+class IActionButton(IButton):
+    """Action button interface"""
+
+    label = TextLine(title="Button label",
+                     description="Button label displayed as hint",
+                     required=False)
+
+    label_css_class = TextLine(title="Label icon CSS class",
+                               description="CSS class associated with label",
+                               required=True,
+                               default='fa fa-fw fa-edit')
+
+    click_handler = TextLine(title="Button click handler",
+                             description="Javascript function called by button click",
+                             required=False)
+
+    url = TextLine(title="Button target URL",
+                   description="Target URL accessed by button click",
+                   required=False)
+
+    modal_target = Bool(title="Modal target?",
+                        description="If True, target URL is opened in a modal frame",
+                        required=False,
+                        default=False)
+
+
+@implementer(IActionButton)
+class ActionButton(Button):
+    """Action button"""
+
+    label_css_class = FieldProperty(IActionButton['label_css_class'])
+    click_handler = FieldProperty(IActionButton['click_handler'])
+    url = FieldProperty(IActionButton['url'])
+    modal_target = FieldProperty(IActionButton['modal_target'])
+
+    def __init__(self, *args, **kwargs):
+        if 'label_css_class' in kwargs:
+            self.label_css_class = kwargs.pop('label_css_class')
+        self.click_handler = kwargs.pop('click_handler', None)
+        self.url = kwargs.pop('url', None)
+        self.modal_target = kwargs.pop('modal_target', None)
+        super(ActionButton, self).__init__(*args, **kwargs)
--- a/src/pyams_form/widget/__init__.py	Fri May 18 15:54:52 2018 +0200
+++ b/src/pyams_form/widget/__init__.py	Fri May 18 15:55:15 2018 +0200
@@ -22,8 +22,8 @@
 # import interfaces
 from pyams_form.interfaces.form import IFormLayer, IResetWidget, ICloseWidget, IDateWidget, IDatetimeWidget, \
     ITimeWidget, \
-    IColorWidget, IHTMLWidget, ISelect2Widget, ITextLineListWidget, ISEOTextLineWidget
-from pyams_form.schema import IResetButton, ICloseButton
+    IColorWidget, IHTMLWidget, ISelect2Widget, ITextLineListWidget, ISEOTextLineWidget, IActionWidget
+from pyams_form.schema import IResetButton, ICloseButton, IActionButton
 from pyams_skin.interfaces.tinymce import ITinyMCEConfiguration
 from pyams_utils.schema import IColorField, IHTMLField, ITextLineListField
 from pyramid.interfaces import IRequest
@@ -37,6 +37,7 @@
 from pyams_utils.timezone import tztime, localgmtime
 from pyramid.exceptions import ConfigurationError
 from z3c.form.action import Action
+from z3c.form.browser.button import ButtonWidget
 from z3c.form.browser.select import SelectWidget
 from z3c.form.browser.submit import SubmitWidget
 from z3c.form.browser.text import TextWidget
@@ -45,6 +46,7 @@
 from z3c.form.converter import BaseDataConverter, DatetimeDataConverter as BaseDatetimeDataConverter
 from z3c.form.widget import FieldWidget, WidgetTemplateFactory, WidgetLayoutFactory
 from zope.interface import implementer_only, directlyProvides, Interface
+from zope.schema.fieldproperty import FieldProperty
 
 from pyams_form import _
 
@@ -212,6 +214,43 @@
 
 
 #
+# Action button widget and action
+#
+
+@widgettemplate_config(mode=INPUT_MODE, template='templates/action-input.pt', layer=IFormLayer)
+@widgettemplate_config(mode=DISPLAY_MODE, template='templates/action-display.pt', layer=IFormLayer)
+@implementer_only(IActionWidget)
+class ActionWidget(ButtonWidget):
+    """A dialog action button"""
+
+    label_css_class = FieldProperty(IActionWidget['label_css_class'])
+    click_handler = FieldProperty(IActionWidget['click_handler'])
+    url = FieldProperty(IActionWidget['url'])
+    modal_target = FieldProperty(IActionWidget['modal_target'])
+
+
+@adapter_config(context=(IActionButton, IFormLayer), provides=IFieldWidget)
+def ActionFieldWidget(field, request):
+    action = FieldWidget(field, ActionWidget(request))
+    action.value = field.title
+    return action
+
+
+@adapter_config(context=(IFormLayer, IActionButton), provides=IButtonAction)
+class ActionButtonAction(ActionWidget, ButtonAction):
+    """Action button action"""
+
+    def __init__(self, request, field):
+        ActionWidget.__init__(self, request)
+        Action.__init__(self, request, field.title)
+        self.field = field
+        self.label_css_class = field.label_css_class
+        self.click_handler = field.click_handler
+        self.url = field.url
+        self.modal_target = field.modal_target
+
+
+#
 # Date widget
 #
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_form/widget/templates/action-display.pt	Fri May 18 15:55:15 2018 +0200
@@ -0,0 +1,31 @@
+<button type="button"
+		class="btn padding-x-5 hint opaque baseline"
+		tal:define="url extension:absolute_url(view.form.context, view.url)"
+		tal:attributes="id view/id;
+						title view/title;
+						style view/style;
+						lang view/lang;
+						onclick view/onclick;
+						ondblclick view/ondblclick;
+						onmousedown view/onmousedown;
+						onmouseup view/onmouseup;
+						onmouseover view/onmouseover;
+						onmousemove view/onmousemove;
+						onmouseout view/onmouseout;
+						onkeypress view/onkeypress;
+						onkeydown view/onkeydown;
+						onkeyup view/onkeyup;
+						value view/value;
+						disabled view/disabled;
+						tabindex view/tabindex;
+						onfocus view/onfocus;
+						onblur view/onblur;
+						onchange view/onchange;
+						alt view/alt;
+						accesskey view/accesskey;
+						data-ams-url python:url if view.url else None;
+						data-ams-click-handler view/click_handler;
+						data-toggle python:'modal' if view.modal_target else None;
+						data-ams-data extension:object_data(view);">
+	<i tal:attributes="class view/label_css_class"></i>
+</button>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_form/widget/templates/action-input.pt	Fri May 18 15:55:15 2018 +0200
@@ -0,0 +1,32 @@
+<button type="button"
+		class="btn padding-x-5 hint opaque baseline"
+		tal:define="url extension:absolute_url(view.form.context, view.url)"
+		tal:attributes="id view/id;
+						title view/title;
+						style view/style;
+						lang view/lang;
+						onclick view/onclick;
+						ondblclick view/ondblclick;
+						onmousedown view/onmousedown;
+						onmouseup view/onmouseup;
+						onmouseover view/onmouseover;
+						onmousemove view/onmousemove;
+						onmouseout view/onmouseout;
+						onkeypress view/onkeypress;
+						onkeydown view/onkeydown;
+						onkeyup view/onkeyup;
+						value view/value;
+						disabled view/disabled;
+						tabindex view/tabindex;
+						onfocus view/onfocus;
+						onblur view/onblur;
+						onchange view/onchange;
+						alt view/alt;
+						accesskey view/accesskey;
+						data-ams-url python:url if view.url else None;
+						data-ams-click-handler view/click_handler;
+						data-toggle python:'modal' if view.modal_target else None;
+						data-ams-data extension:object_data(view);"
+		data-ams-hint-gravity="s">
+	<i tal:attributes="class view/label_css_class"></i>
+</button>