From 22962f1bc7a77cba7689f75f9bded458ffbac5ab Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Mon, 23 May 2016 13:56:49 +0200 Subject: [PATCH 1/7] Remove Archetypes based JavaScript code. --- CHANGES.rst | 3 ++ plone/app/event/browser/resources/event.js | 41 ++++++++-------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 58cf32cbc..628993be5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,6 +14,9 @@ New features: Bug fixes: +- Remove Archetypes based JavaScript code. + [thet] + - Don't validate the ``validate_start_end`` invariant, if start or end are ``None``. This can happen on non-required, default empty start or end fields during editing. [thet] diff --git a/plone/app/event/browser/resources/event.js b/plone/app/event/browser/resources/event.js index dba0649e3..fb0dcefc3 100644 --- a/plone/app/event/browser/resources/event.js +++ b/plone/app/event/browser/resources/event.js @@ -1,12 +1,12 @@ -/*jslint browser: true*/ -/*global $, jQuery, plone, require*/ +/* jslint browser: true */ +/* globals require */ if(require === undefined){ require = function(reqs, torun){ 'use strict'; return torun(window.jQuery); - } + }; } @@ -17,16 +17,6 @@ require([ var end_start_delta = 1 / 24; // Delta in days - function a_or_b(a, b) { - var ret; - if (a.length > 0) { - ret = a; - } else { - ret = b; - } - return ret; - } - function getDateTime(datetimewidget) { var date, time, datetime; date = $('input[name="_submit"]:first', datetimewidget).prop('value'); @@ -50,16 +40,16 @@ require([ function initDelta() { var start_datetime, end_datetime; - start_datetime = getDateTime(a_or_b($('#formfield-form-widgets-IEventBasic-start'), $('#archetypes-fieldname-startDate'))); - end_datetime = getDateTime(a_or_b($('#formfield-form-widgets-IEventBasic-end'), $('#archetypes-fieldname-endDate'))); + start_datetime = getDateTime($('#formfield-form-widgets-IEventBasic-start')); + end_datetime = getDateTime($('#formfield-form-widgets-IEventBasic-end')); // delta in days end_start_delta = (end_datetime - start_datetime) / 1000 / 60; } function updateEndDate() { var jq_start, jq_end, start_date, new_end_date; - jq_start = a_or_b($('#formfield-form-widgets-IEventBasic-start'), $('#archetypes-fieldname-startDate')); - jq_end = a_or_b($('#formfield-form-widgets-IEventBasic-end'), $('#archetypes-fieldname-endDate')); + jq_start = $('#formfield-form-widgets-IEventBasic-start'); + jq_end = $('#formfield-form-widgets-IEventBasic-end'); start_date = getDateTime(jq_start); new_end_date = new Date(start_date); @@ -71,8 +61,8 @@ require([ function validateEndDate() { var jq_start, jq_end, start_datetime, end_datetime; - jq_start = a_or_b($('#formfield-form-widgets-IEventBasic-start'), $('#archetypes-fieldname-startDate')); - jq_end = a_or_b($('#formfield-form-widgets-IEventBasic-end'), $('#archetypes-fieldname-endDate')); + jq_start = $('#formfield-form-widgets-IEventBasic-start'); + jq_end = $('#formfield-form-widgets-IEventBasic-end'); start_datetime = getDateTime(jq_start); end_datetime = getDateTime(jq_end); @@ -141,24 +131,23 @@ require([ var jq_whole_day, jq_time, jq_open_end, jq_end, jq_start; // WHOLE DAY INIT - jq_whole_day = a_or_b($('#formfield-form-widgets-IEventBasic-whole_day input'), $('form[name="edit_form"] input#wholeDay')); - jq_time = a_or_b($('#formfield-form-widgets-IEventBasic-start .pattern-pickadate-time-wrapper, #formfield-form-widgets-IEventBasic-end .pattern-pickadate-time-wrapper'), - $('#archetypes-fieldname-startDate .pattern-pickadate-time-wrapper, #archetypes-fieldname-endDate .pattern-pickadate-time-wrapper')); + jq_whole_day = $('#formfield-form-widgets-IEventBasic-whole_day input'); + jq_time = $('#formfield-form-widgets-IEventBasic-start .pattern-pickadate-time-wrapper, #formfield-form-widgets-IEventBasic-end .pattern-pickadate-time-wrapper'); if (jq_whole_day.length > 0) { jq_whole_day.bind('change', function (e) { show_hide_widget(jq_time, e.target.checked, true); }); show_hide_widget(jq_time, jq_whole_day.get(0).checked, false); } // OPEN END INIT - jq_open_end = a_or_b($('#formfield-form-widgets-IEventBasic-open_end input'), $('form[name="edit_form"] input#openEnd')); - jq_end = a_or_b($('#formfield-form-widgets-IEventBasic-end'), $('#archetypes-fieldname-endDate')); + jq_open_end = $('#formfield-form-widgets-IEventBasic-open_end input'); + jq_end = $('#formfield-form-widgets-IEventBasic-end'); if (jq_open_end.length > 0) { jq_open_end.bind('change', function (e) { show_hide_widget(jq_end, e.target.checked, true); }); show_hide_widget(jq_end, jq_open_end.get(0).checked, false); } // START/END SETTING/VALIDATION - jq_start = a_or_b($('#formfield-form-widgets-IEventBasic-start'), $('#archetypes-fieldname-startDate')); + jq_start = $('#formfield-form-widgets-IEventBasic-start'); jq_start.each(function () { $(this).on('focus', '.picker__input', initDelta); $(this).on('change', '.picker__input', updateEndDate); @@ -171,7 +160,7 @@ require([ // EVENT LISTING CALENDAR POPUP event_listing_calendar_init($("#event_listing_calendar")); - }; + } // mockup-core should trigger event once it initiallized all patterns (in // mockup-core) but it only sets body class once all patterns were From 562e765495f63e71bb9eed4d8ac4bbac3b4be4cc Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Mon, 23 May 2016 15:45:00 +0200 Subject: [PATCH 2/7] Use ``plone.autoform.directives`` for manipulating field widgets instead of overriding the default Fieldwidget adapters. --- CHANGES.rst | 3 +- plone/app/event/dx/behaviors.py | 90 +++++++++++++++---------------- plone/app/event/dx/configure.zcml | 4 -- 3 files changed, 46 insertions(+), 51 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 628993be5..35a4a82d0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,7 +10,8 @@ Breaking changes: New features: -- *add item here* +- Use ``plone.autoform.directives`` for manipulating field widgets instead of overriding the default Fieldwidget adapters. + [thet] Bug fixes: diff --git a/plone/app/event/dx/behaviors.py b/plone/app/event/dx/behaviors.py index 755ff67ac..7f8342b51 100644 --- a/plone/app/event/dx/behaviors.py +++ b/plone/app/event/dx/behaviors.py @@ -1,14 +1,11 @@ """Behaviors to enable calendarish event extension to dexterity content types. """ -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.utils import getFSVersionTuple -from Products.CMFPlone.utils import safe_unicode from plone.app.dexterity.behaviors.metadata import ICategorization from plone.app.event import messageFactory as _ -from plone.app.event.base import DT from plone.app.event.base import default_end as default_end_dt from plone.app.event.base import default_start as default_start_dt from plone.app.event.base import default_timezone +from plone.app.event.base import DT from plone.app.event.base import dt_end_of_day from plone.app.event.base import dt_start_of_day from plone.app.event.base import first_weekday @@ -16,25 +13,25 @@ from plone.app.event.dx.interfaces import IDXEvent from plone.app.event.dx.interfaces import IDXEventRecurrence from plone.app.textfield.value import RichTextValue -from plone.app.z3cform.interfaces import IPloneFormLayer -from plone.autoform import directives as form +from plone.autoform import directives from plone.autoform.interfaces import IFormFieldProvider from plone.event.interfaces import IEventAccessor from plone.event.utils import pydt from plone.event.utils import utc -from plone.formwidget.recurrence.z3cform.widget import RecurrenceWidget +from plone.formwidget.recurrence.z3cform.widget import RecurrenceFieldWidget from plone.indexer import indexer from plone.supermodel import model from plone.uuid.interfaces import IUUID +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.utils import getFSVersionTuple +from Products.CMFPlone.utils import safe_unicode +from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget from z3c.form.browser.textlines import TextLinesFieldWidget -from z3c.form.interfaces import IFieldWidget -from z3c.form.util import getSpecification -from z3c.form.widget import FieldWidget from zope import schema from zope.component import adapter -from zope.interface import Invalid from zope.interface import alsoProvides from zope.interface import implementer +from zope.interface import Invalid from zope.interface import invariant from zope.interface import provider from zope.schema.interfaces import IContextAwareDefaultFactory @@ -44,10 +41,10 @@ if PLONE5: # Plone 5 - from plone.app.z3cform.widget import DatetimeWidget + from plone.app.z3cform.widget import DatetimeFieldWidget else: # Plone 4 - from plone.app.widgets.dx import DatetimeWidget + from plone.app.widgets.dx import DatetimeFieldWidget def first_weekday_sun0(): @@ -74,6 +71,7 @@ def default_end(context): class IEventBasic(model.Schema, IDXEvent): + """ Basic event schema. """ start = schema.Datetime( @@ -88,6 +86,11 @@ class IEventBasic(model.Schema, IDXEvent): required=True, defaultFactory=default_start ) + directives.widget( + 'start', + DatetimeFieldWidget, + default_timezone=default_timezone + ) end = schema.Datetime( title=_( @@ -101,6 +104,11 @@ class IEventBasic(model.Schema, IDXEvent): required=True, defaultFactory=default_end ) + directives.widget( + 'end', + DatetimeFieldWidget, + default_timezone=default_timezone + ) whole_day = schema.Bool( title=_( @@ -114,6 +122,10 @@ class IEventBasic(model.Schema, IDXEvent): required=False, default=False ) + directives.widget( + 'whole_day', + SingleCheckBoxFieldWidget + ) open_end = schema.Bool( title=_( @@ -127,10 +139,14 @@ class IEventBasic(model.Schema, IDXEvent): required=False, default=False ) + directives.widget( + 'open_end', + SingleCheckBoxFieldWidget + ) # icalendar event uid sync_uid = schema.TextLine(required=False) - form.mode(sync_uid='hidden') + directives.mode(sync_uid='hidden') @invariant def validate_start_end(data): @@ -146,23 +162,8 @@ def validate_start_end(data): ) -@adapter(getSpecification(IEventBasic['start']), IPloneFormLayer) -@implementer(IFieldWidget) -def StartDateFieldWidget(field, request): - widget = FieldWidget(field, DatetimeWidget(request)) - widget.default_timezone = default_timezone - return widget - - -@adapter(getSpecification(IEventBasic['end']), IPloneFormLayer) -@implementer(IFieldWidget) -def EndDateFieldWidget(field, request): - widget = FieldWidget(field, DatetimeWidget(request)) - widget.default_timezone = default_timezone - return widget - - class IEventRecurrence(model.Schema, IDXEventRecurrence): + """ Recurring Event Schema. """ recurrence = schema.Text( @@ -177,23 +178,17 @@ class IEventRecurrence(model.Schema, IDXEventRecurrence): required=False, default=None ) - - -@adapter(getSpecification(IEventRecurrence['recurrence']), IPloneFormLayer) -@implementer(IFieldWidget) -def RecurrenceFieldWidget(field, request): - # Please note: If you create a new behavior with superclasses IEventBasic - # and IRecurrence, then you have to reconfigure the dotted path value of - # the start_field parameter for the RecurrenceWidget to the new - # behavior name, like: IMyNewBehaviorName.start. - widget = FieldWidget(field, RecurrenceWidget(request)) - widget.start_field = 'IEventBasic.start' - widget.first_day = first_weekday_sun0 - widget.show_repeat_forever = False - return widget + directives.widget( + 'recurrence', + RecurrenceFieldWidget, + start_field=u'IEventBasic.start', + first_day=first_weekday_sun0, + show_repeat_forever=False + ) class IEventLocation(model.Schema): + """ Event Location Schema. """ location = schema.TextLine( @@ -211,6 +206,7 @@ class IEventLocation(model.Schema): class IEventAttendees(model.Schema): + """ Event Attendees Schema. """ attendees = schema.Tuple( @@ -227,10 +223,11 @@ class IEventAttendees(model.Schema): missing_value=(), default=(), ) - form.widget(attendees=TextLinesFieldWidget) + directives.widget(attendees=TextLinesFieldWidget) class IEventContact(model.Schema): + """ Event Contact Schema. """ contact_name = schema.TextLine( @@ -310,7 +307,7 @@ class IEventContact(model.Schema): """ -## Attribute indexer +# Attribute indexer # Start indexer @indexer(IDXEvent) @@ -368,6 +365,7 @@ def searchable_text_indexer(obj): @adapter(IDXEvent) @implementer(IEventAccessor) class EventAccessor(object): + """Generic event accessor adapter implementation for Dexterity content objects. """ diff --git a/plone/app/event/dx/configure.zcml b/plone/app/event/dx/configure.zcml index de98d711d..c64fe8d97 100644 --- a/plone/app/event/dx/configure.zcml +++ b/plone/app/event/dx/configure.zcml @@ -20,10 +20,6 @@ - - - - From 2b67447b7592ed9f743985464a77aebedc8c1c06 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Mon, 23 May 2016 15:52:41 +0200 Subject: [PATCH 3/7] Configure custom css classes for all event behavior fields. This makes it easier to use same selectors also for derived behaviors. --- CHANGES.rst | 4 +++ plone/app/event/dx/behaviors.py | 47 ++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 35a4a82d0..2ff4471b3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,10 @@ Breaking changes: New features: +- Configure custom css classes for all event behavior fields. + This makes it easier to use same selectors also for derived behaviors. + [thet] + - Use ``plone.autoform.directives`` for manipulating field widgets instead of overriding the default Fieldwidget adapters. [thet] diff --git a/plone/app/event/dx/behaviors.py b/plone/app/event/dx/behaviors.py index 7f8342b51..688491f29 100644 --- a/plone/app/event/dx/behaviors.py +++ b/plone/app/event/dx/behaviors.py @@ -26,6 +26,7 @@ from Products.CMFPlone.utils import getFSVersionTuple from Products.CMFPlone.utils import safe_unicode from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget +from z3c.form.browser.text import TextFieldWidget from z3c.form.browser.textlines import TextLinesFieldWidget from zope import schema from zope.component import adapter @@ -89,7 +90,8 @@ class IEventBasic(model.Schema, IDXEvent): directives.widget( 'start', DatetimeFieldWidget, - default_timezone=default_timezone + default_timezone=default_timezone, + klass=u'event_start' ) end = schema.Datetime( @@ -107,7 +109,8 @@ class IEventBasic(model.Schema, IDXEvent): directives.widget( 'end', DatetimeFieldWidget, - default_timezone=default_timezone + default_timezone=default_timezone, + klass=u'event_end' ) whole_day = schema.Bool( @@ -124,7 +127,8 @@ class IEventBasic(model.Schema, IDXEvent): ) directives.widget( 'whole_day', - SingleCheckBoxFieldWidget + SingleCheckBoxFieldWidget, + klass=u'event_whole_day' ) open_end = schema.Bool( @@ -141,7 +145,8 @@ class IEventBasic(model.Schema, IDXEvent): ) directives.widget( 'open_end', - SingleCheckBoxFieldWidget + SingleCheckBoxFieldWidget, + klass=u'event_open_end' ) # icalendar event uid @@ -183,7 +188,8 @@ class IEventRecurrence(model.Schema, IDXEventRecurrence): RecurrenceFieldWidget, start_field=u'IEventBasic.start', first_day=first_weekday_sun0, - show_repeat_forever=False + show_repeat_forever=False, + klass=u'event_recurrence' ) @@ -203,6 +209,11 @@ class IEventLocation(model.Schema): required=False, default=None ) + directives.widget( + 'location', + TextFieldWidget, + klass=u'event_location' + ) class IEventAttendees(model.Schema): @@ -223,7 +234,11 @@ class IEventAttendees(model.Schema): missing_value=(), default=(), ) - directives.widget(attendees=TextLinesFieldWidget) + directives.widget( + 'attendees', + TextLinesFieldWidget, + klass=u'event_attendees' + ) class IEventContact(model.Schema): @@ -242,6 +257,11 @@ class IEventContact(model.Schema): required=False, default=None ) + directives.widget( + 'contact_name', + TextFieldWidget, + klass=u'event_contact_name' + ) contact_email = schema.TextLine( title=_( @@ -255,6 +275,11 @@ class IEventContact(model.Schema): required=False, default=None ) + directives.widget( + 'contact_email', + TextFieldWidget, + klass=u'event_contact_email' + ) contact_phone = schema.TextLine( title=_( @@ -268,6 +293,11 @@ class IEventContact(model.Schema): required=False, default=None ) + directives.widget( + 'contact_phone', + TextFieldWidget, + klass=u'event_contact_phone' + ) event_url = schema.TextLine( title=_( @@ -282,6 +312,11 @@ class IEventContact(model.Schema): required=False, default=None ) + directives.widget( + 'contact_url', + TextFieldWidget, + klass=u'event_contact_url' + ) # Mark these interfaces as form field providers From 6d90c7c69ac2b7feffcf81ff6e3aa9594d13d752 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Tue, 24 May 2016 00:40:56 +0200 Subject: [PATCH 4/7] fix directives field name reference --- plone/app/event/dx/behaviors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plone/app/event/dx/behaviors.py b/plone/app/event/dx/behaviors.py index 688491f29..5e03260ba 100644 --- a/plone/app/event/dx/behaviors.py +++ b/plone/app/event/dx/behaviors.py @@ -313,9 +313,9 @@ class IEventContact(model.Schema): default=None ) directives.widget( - 'contact_url', + 'event_url', TextFieldWidget, - klass=u'event_contact_url' + klass=u'event_url' ) From d8c6dbf630dd256cb16eff2215e96c00b2ca696b Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 25 May 2016 04:16:47 +0200 Subject: [PATCH 5/7] Make use of more generic selectors in JavaScript, so that JavaScript works also for derived classes. --- CHANGES.rst | 3 + plone/app/event/browser/resources/event.js | 74 +++++++++++----------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2ff4471b3..cd81572e5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,9 @@ Breaking changes: New features: +- Make use of more generic selectors in JavaScript, so that JavaScript works also for derived classes. + [thet] + - Configure custom css classes for all event behavior fields. This makes it easier to use same selectors also for derived behaviors. [thet] diff --git a/plone/app/event/browser/resources/event.js b/plone/app/event/browser/resources/event.js index fb0dcefc3..f8f63ed98 100644 --- a/plone/app/event/browser/resources/event.js +++ b/plone/app/event/browser/resources/event.js @@ -38,39 +38,30 @@ require([ return datetime; } - function initDelta() { - var start_datetime, end_datetime; - start_datetime = getDateTime($('#formfield-form-widgets-IEventBasic-start')); - end_datetime = getDateTime($('#formfield-form-widgets-IEventBasic-end')); + function initDelta(a, b) { + var start_datetime = getDateTime(a); + var end_datetime = getDateTime(b); // delta in days end_start_delta = (end_datetime - start_datetime) / 1000 / 60; } - function updateEndDate() { - var jq_start, jq_end, start_date, new_end_date; - jq_start = $('#formfield-form-widgets-IEventBasic-start'); - jq_end = $('#formfield-form-widgets-IEventBasic-end'); - - start_date = getDateTime(jq_start); - new_end_date = new Date(start_date); + function updateEndDate(start_container, end_container) { + var start_date = getDateTime(start_container); + var new_end_date = new Date(start_date); new_end_date.setMinutes(start_date.getMinutes() + end_start_delta); - $('.pattern-pickadate-date', jq_end).pickadate('picker').set('select', new_end_date); - $('.pattern-pickadate-time', jq_end).pickatime('picker').set('select', new_end_date); + $('.pattern-pickadate-date', end_container).pickadate('picker').set('select', new_end_date); + $('.pattern-pickadate-time', end_container).pickatime('picker').set('select', new_end_date); } - function validateEndDate() { - var jq_start, jq_end, start_datetime, end_datetime; - jq_start = $('#formfield-form-widgets-IEventBasic-start'); - jq_end = $('#formfield-form-widgets-IEventBasic-end'); - - start_datetime = getDateTime(jq_start); - end_datetime = getDateTime(jq_end); + function validateEndDate(start_container, end_container) { + var start_datetime = getDateTime(start_container); + var end_datetime = getDateTime(end_container); if (end_datetime < start_datetime) { - jq_end.addClass("error"); + start_container.addClass("error"); } else { - jq_end.removeClass("error"); + end_container.removeClass("error"); } } @@ -127,32 +118,41 @@ require([ function initilize_event() { // EDIT FORM - - var jq_whole_day, jq_time, jq_open_end, jq_end, jq_start; + var $start_input = $('form input.event_start'); + var $start_container = $start_input.closest('div'); + var $pickadate_starttime = $('.pattern-pickadate-time-wrapper', $start_container); + + var $end_input = $('form input.event_end'); + var $end_container = $end_input.closest('div'); + var $pickadate_endtime = $('.pattern-pickadate-time-wrapper', $end_container); + + var $whole_day_input = $('form input.event_whole_day'); + var $open_end_input = $('form input.open_end_input'); // WHOLE DAY INIT - jq_whole_day = $('#formfield-form-widgets-IEventBasic-whole_day input'); - jq_time = $('#formfield-form-widgets-IEventBasic-start .pattern-pickadate-time-wrapper, #formfield-form-widgets-IEventBasic-end .pattern-pickadate-time-wrapper'); - if (jq_whole_day.length > 0) { - jq_whole_day.bind('change', function (e) { show_hide_widget(jq_time, e.target.checked, true); }); - show_hide_widget(jq_time, jq_whole_day.get(0).checked, false); + if ($whole_day_input.length > 0) { + $whole_day_input.bind('change', function (e) { + show_hide_widget($pickadate_starttime, e.target.checked, true); + show_hide_widget($pickadate_endtime, e.target.checked, true); + }); + show_hide_widget($pickadate_starttime, $whole_day_input.get(0).checked, false); + show_hide_widget($pickadate_endtime, $whole_day_input.get(0).checked, false); } // OPEN END INIT - jq_open_end = $('#formfield-form-widgets-IEventBasic-open_end input'); - jq_end = $('#formfield-form-widgets-IEventBasic-end'); - if (jq_open_end.length > 0) { - jq_open_end.bind('change', function (e) { show_hide_widget(jq_end, e.target.checked, true); }); - show_hide_widget(jq_end, jq_open_end.get(0).checked, false); + if ($open_end_input.length > 0) { + $open_end_input.bind('change', function (e) { + show_hide_widget($end_container, e.target.checked, true); + }); + show_hide_widget($end_container, $open_end_input.get(0).checked, false); } // START/END SETTING/VALIDATION - jq_start = $('#formfield-form-widgets-IEventBasic-start'); - jq_start.each(function () { + $start_container.each(function () { $(this).on('focus', '.picker__input', initDelta); $(this).on('change', '.picker__input', updateEndDate); }); - jq_end.each(function () { + $end_container.each(function () { $(this).on('focus', '.picker__input', initDelta); $(this).on('change', '.picker__input', validateEndDate); }); From d2e89a07f6bc54364a0749a514995bce14031945 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 25 May 2016 10:04:05 +0200 Subject: [PATCH 6/7] raise major version to 3.0, as we depend now on plone.app.z3cform>=2.0.1.dev0, which is only available for Plone >= 5.1 --- CHANGES.rst | 10 ++++++++-- setup.py | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cd81572e5..2c2033f00 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,11 +1,16 @@ Changelog ========= -2.0.10 (unreleased) -------------------- +3.0.0 (unreleased) +------------------ Breaking changes: +.. note:: + This release depends on ``plone.app.z3cform >= 2.0.1``, which is only available for Plone 5.1. + This is a backwards incompatible change, which satisfy a major version change for plone.app.event. + Consequently, Plone 4 compatibility code will be removed in this release. + - *add item here* New features: @@ -15,6 +20,7 @@ New features: - Configure custom css classes for all event behavior fields. This makes it easier to use same selectors also for derived behaviors. + Needs ``plone.app.z3cform >= 2.0.1``. [thet] - Use ``plone.autoform.directives`` for manipulating field widgets instead of overriding the default Fieldwidget adapters. diff --git a/setup.py b/setup.py index 1d72ef274..1448ac5c1 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import os -version = '2.0.10.dev0' +version = '3.0.dev0' setup( @@ -53,7 +53,7 @@ 'plone.app.registry', 'plone.app.textfield', 'plone.app.vocabularies >= 2.1.15.dev0', - 'plone.app.z3cform', + 'plone.app.z3cform>=2.0.1.dev0', 'plone.autoform>=1.4', 'plone.behavior', 'plone.browserlayer', From 1191f0ae00569ec75a80c75e161ab163e84b8bc5 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 25 May 2016 12:12:13 +0200 Subject: [PATCH 7/7] Make JavaScript date/time update work with optional start/end dates. + Bugfixes --- CHANGES.rst | 3 ++ plone/app/event/browser/resources/event.js | 56 +++++++++++++++------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2c2033f00..345a57d03 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,9 @@ Breaking changes: New features: +- Make JavaScript date/time update work with optional start/end dates. + [thet] + - Make use of more generic selectors in JavaScript, so that JavaScript works also for derived classes. [thet] diff --git a/plone/app/event/browser/resources/event.js b/plone/app/event/browser/resources/event.js index f8f63ed98..bc1c3ab8d 100644 --- a/plone/app/event/browser/resources/event.js +++ b/plone/app/event/browser/resources/event.js @@ -15,13 +15,21 @@ require([ ], function($){ 'use strict'; - var end_start_delta = 1 / 24; // Delta in days + var start_end_delta = 1 / 24; // Delta in days function getDateTime(datetimewidget) { - var date, time, datetime; + var date, time, datetime, set_time; date = $('input[name="_submit"]:first', datetimewidget).prop('value'); + if (! date) { + return; + } date = date.split("-"); - time = $('input[name="_submit"]:last', datetimewidget).prop('value') || '00:00'; + time = $('input[name="_submit"]:last', datetimewidget).prop('value'); + if (! time) { + // can happen with optional start/end dates without default values. + set_time = true; + time = '00:00'; + } time = time.split(":"); // We can't just parse the ``date + 'T' + time`` string, because of @@ -35,20 +43,33 @@ require([ parseInt(time[0], 10), parseInt(time[1], 10) ); + if (set_time) { + // we have a date but no time?! set it. + $('.pattern-pickadate-time', datetimewidget).pickatime('picker').set('select', datetime); + } return datetime; } - function initDelta(a, b) { - var start_datetime = getDateTime(a); - var end_datetime = getDateTime(b); + function initStartEndDelta(start_container, end_container) { + var start_datetime = getDateTime(start_container); + var end_datetime = getDateTime(end_container); + + if (! start_datetime || ! end_datetime) { + return; + } + // delta in days - end_start_delta = (end_datetime - start_datetime) / 1000 / 60; + start_end_delta = (end_datetime - start_datetime) / 1000 / 60; } function updateEndDate(start_container, end_container) { var start_date = getDateTime(start_container); + if (! start_date) { + return; + } + var new_end_date = new Date(start_date); - new_end_date.setMinutes(start_date.getMinutes() + end_start_delta); + new_end_date.setMinutes(start_date.getMinutes() + start_end_delta); $('.pattern-pickadate-date', end_container).pickadate('picker').set('select', new_end_date); $('.pattern-pickadate-time', end_container).pickatime('picker').set('select', new_end_date); @@ -57,6 +78,9 @@ require([ function validateEndDate(start_container, end_container) { var start_datetime = getDateTime(start_container); var end_datetime = getDateTime(end_container); + if (! start_datetime || ! end_datetime) { + return; + } if (end_datetime < start_datetime) { start_container.addClass("error"); @@ -121,13 +145,13 @@ require([ var $start_input = $('form input.event_start'); var $start_container = $start_input.closest('div'); var $pickadate_starttime = $('.pattern-pickadate-time-wrapper', $start_container); - + var $end_input = $('form input.event_end'); var $end_container = $end_input.closest('div'); var $pickadate_endtime = $('.pattern-pickadate-time-wrapper', $end_container); - + var $whole_day_input = $('form input.event_whole_day'); - var $open_end_input = $('form input.open_end_input'); + var $open_end_input = $('form input.event_open_end'); // WHOLE DAY INIT if ($whole_day_input.length > 0) { @@ -149,12 +173,12 @@ require([ // START/END SETTING/VALIDATION $start_container.each(function () { - $(this).on('focus', '.picker__input', initDelta); - $(this).on('change', '.picker__input', updateEndDate); + $(this).on('focus', '.picker__input', function () { initStartEndDelta($start_container, $end_container); }); + $(this).on('change', '.picker__input', function () { updateEndDate($start_container, $end_container); }); }); $end_container.each(function () { - $(this).on('focus', '.picker__input', initDelta); - $(this).on('change', '.picker__input', validateEndDate); + $(this).on('focus', '.picker__input', function () { initStartEndDelta($start_container, $end_container); }); + $(this).on('change', '.picker__input', function () { validateEndDate($start_container, $end_container); }); }); // EVENT LISTING CALENDAR POPUP @@ -171,5 +195,5 @@ require([ initilize_event(); } }, 100); - + });