From bcf2952980e554deee43eeb33b4e8ff659e48375 Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Wed, 4 Mar 2015 23:35:52 +0100 Subject: [PATCH] [gen] Calendar field: more work on multi-events and validation within timeline calendars. --- fields/calendar.py | 132 +++++++++++++++++++++++++++------------------ gen/tr/Appy.pot | 4 ++ gen/tr/ar.po | 4 ++ gen/tr/de.po | 4 ++ gen/tr/en.po | 4 ++ gen/tr/es.po | 4 ++ gen/tr/fr.po | 4 ++ gen/tr/it.po | 4 ++ gen/tr/nl.po | 4 ++ gen/ui/angled.png | Bin 0 -> 209 bytes 10 files changed, 113 insertions(+), 51 deletions(-) create mode 100644 gen/ui/angled.png diff --git a/fields/calendar.py b/fields/calendar.py index a8e3897..9c19edf 100644 --- a/fields/calendar.py +++ b/fields/calendar.py @@ -93,6 +93,10 @@ class Other: info.name = eventNames[eventType] res.append(info) + def mayValidate(self): + '''Is validation enabled for this other calendar?''' + return self.field.mayValidate(self.obj) + # ------------------------------------------------------------------------------ class Event(Persistent): '''An event as will be stored in the database''' @@ -159,19 +163,15 @@ class Calendar(Field): # Legend for a timeline calendar pxTimelineLegend = Px(''' - - - + var="items=field.getLegendItems(allEventTypes, allEventNames, \ + colors, url, _)"> + + + - +
- - - - -
 
-
+ +
 
:allEventNames[eventType]:item.name
''') @@ -201,7 +201,8 @@ class Calendar(Field): + var2="tlName=field.getTimelineName(other); + mayValidate=mayValidate and other.mayValidate()"> ::tlName ::field.getTimelineCell(events) + events)">::field.getTimelineCell(date, other, events, mayValidate) ::tlName @@ -682,11 +683,63 @@ class Calendar(Field): return '%s' % (other.obj.url, other.obj.title) return self.timelineName(self, other) - def getTimelineCell(self, events): - '''Gets the content of a cell in a timeline calendar.''' - # Currently a single event is allowed - if not events or not events[0].symbol: return '' - return events[0].symbol + def getTimelineCell(self, date, other, events, mayValidate): + '''Gets the content of a cell in a timeline calendar''' + if events and mayValidate: + # If at least one event from p_events is in the validation schema, + # propose a unique checkbox, that will allow to validate or not all + # validable events at p_date. + for info in events: + if info.event.eventType in other.field.validation.schema: + return '' + return '' + # When there are multiple events, a background image is already shown + if not events or (len(events) > 1): return '' + # A single event: if not colored, show a symbol + return events[0].symbol or '' + + def getLegendItems(self, allEventTypes, allEventNames, colors, url, _): + '''Gets information needed to produce the legend for a timeline.''' + # Produce one legend item by event type shown and colored + res = [] + for eventType in allEventTypes: + if eventType not in colors: continue + res.append(Object(name=allEventNames[eventType], + style='background-color: %s' % colors[eventType])) + # Add the background indicating that several events are hidden behind + # the timeline cell + res.append(Object(name=_('several_events'), + style=url('angled', bg=True))) + return res + + def getTimelineMonths(self, grid, obj): + '''Given the p_grid of dates, this method returns the list of + corresponding months.''' + res = [] + for date in grid: + if not res: + # Get the month correspoding to the first day in the grid + m = Object(month=date.aMonth(), colspan=1, year=date.year()) + res.append(m) + else: + # Augment current month' colspan or create a new one + current = res[-1] + if date.aMonth() == current.month: + current.colspan += 1 + else: + m = Object(month=date.aMonth(), colspan=1, year=date.year()) + res.append(m) + # Replace month short names by translated names whose format may vary + # according to colspan (a higher colspan allow us to produce a longer + # month name). + for m in res: + text = '%s %d' % (obj.translate('month_%s' % m.month), m.year) + if m.colspan < 6: + # Short version: a single letter with an acronym + m.month = '%s' % (text, text[0]) + else: + m.month = text + return res def getAdditionalInfoAt(self, obj, date, preComputed): '''If the user has specified a method in self.additionalInfo, we call @@ -1144,9 +1197,15 @@ class Calendar(Field): def getCellStyle(self, obj, date, render, events): '''Gets the cell style to apply to the cell corresponding to p_date.''' if render != 'timeline': return '' # Currently, for timelines only - if not events or (len(events) > 1): return '' - event = events[0] - return event.bgColor and ('background-color: %s' % event.bgColor) or '' + if not events: return '' + elif len(events) > 1: + # Return a special background indicating that several events are + # hidden behing this cell. + return 'background-image: url(%s/ui/angled.png)' % \ + obj.getTool().getSiteUrl() + else: + event = events[0] + return event.bgColor and ('background-color: %s' % event.bgColor) or '' def getCellClass(self, obj, date, render, today): '''What CSS class(es) must apply to the table cell representing p_date @@ -1163,35 +1222,6 @@ class Calendar(Field): res.append('cellDashed') return ' '.join(res) - def getTimelineMonths(self, grid, obj): - '''Given the p_grid of dates, this method returns the list of - corresponding months.''' - res = [] - for date in grid: - if not res: - # Get the month correspoding to the first day in the grid - m = Object(month=date.aMonth(), colspan=1, year=date.year()) - res.append(m) - else: - # Augment current month' colspan or create a new one - current = res[-1] - if date.aMonth() == current.month: - current.colspan += 1 - else: - m = Object(month=date.aMonth(), colspan=1, year=date.year()) - res.append(m) - # Replace month short names by translated names whose format may vary - # according to colspan (a higher colspan allow us to produce a longer - # month name). - for m in res: - text = '%s %d' % (obj.translate('month_%s' % m.month), m.year) - if m.colspan < 6: - # Short version: a single letter with an acronym - m.month = '%s' % (text, text[0]) - else: - m.month = text - return res - def splitList(self, l, sub): return sutils.splitList(l, sub) def mayValidate(self, obj): '''May the currently logged user validate wish events ?''' diff --git a/gen/tr/Appy.pot b/gen/tr/Appy.pot index ae4c2d4..9a338be 100644 --- a/gen/tr/Appy.pot +++ b/gen/tr/Appy.pot @@ -715,6 +715,10 @@ msgstr "" msgid "del_next_events" msgstr "" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/tr/ar.po b/gen/tr/ar.po index 52b19fd..7dfb33f 100644 --- a/gen/tr/ar.po +++ b/gen/tr/ar.po @@ -715,6 +715,10 @@ msgstr "" msgid "del_next_events" msgstr "" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/tr/de.po b/gen/tr/de.po index 5d1918b..a849676 100644 --- a/gen/tr/de.po +++ b/gen/tr/de.po @@ -715,6 +715,10 @@ msgstr "" msgid "del_next_events" msgstr "" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/tr/en.po b/gen/tr/en.po index e3e0608..aa89635 100644 --- a/gen/tr/en.po +++ b/gen/tr/en.po @@ -716,6 +716,10 @@ msgstr "Extend the event on the following number of days (leave blank to create msgid "del_next_events" msgstr "Also delete successive events of the same type." +#. Default: "Several events" +msgid "several_events" +msgstr "Several events" + #. Default: "Timeslot" msgid "timeslot" msgstr "Timeslot" diff --git a/gen/tr/es.po b/gen/tr/es.po index e7c2023..ae36095 100644 --- a/gen/tr/es.po +++ b/gen/tr/es.po @@ -715,6 +715,10 @@ msgstr "" msgid "del_next_events" msgstr "" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/tr/fr.po b/gen/tr/fr.po index 108db59..f9e8ff0 100644 --- a/gen/tr/fr.po +++ b/gen/tr/fr.po @@ -716,6 +716,10 @@ msgstr "Étendre l'événement sur le nombre de jours suivants (laissez vide pou msgid "del_next_events" msgstr "Supprimer aussi les événements successifs de même type" +#. Default: "Several events" +msgid "several_events" +msgstr "Plusieurs événements" + #. Default: "Timeslot" msgid "timeslot" msgstr "Plage horaire" diff --git a/gen/tr/it.po b/gen/tr/it.po index 478ed73..5542c1a 100644 --- a/gen/tr/it.po +++ b/gen/tr/it.po @@ -715,6 +715,10 @@ msgstr "" msgid "del_next_events" msgstr "" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/tr/nl.po b/gen/tr/nl.po index 033b841..34d3527 100644 --- a/gen/tr/nl.po +++ b/gen/tr/nl.po @@ -715,6 +715,10 @@ msgstr "Het event uitbreiden naar de volgende dagen (leeg laten om een event aan msgid "del_next_events" msgstr "Verwijder ook alle opeenvolgende events van hetzelfde type" +#. Default: "Several events" +msgid "several_events" +msgstr "" + #. Default: "Timeslot" msgid "timeslot" msgstr "" diff --git a/gen/ui/angled.png b/gen/ui/angled.png new file mode 100644 index 0000000000000000000000000000000000000000..685a491900a48546a06e0a37333ffddd6f21e16f GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^%plANB6FUp{{d2r#X;^)4C~IxyaaOC0(?STYieqi zFJHc~-%uVTT@vIM%;50sMjD8d7^0iXmdKI;Vst0E!PZCIA2c literal 0 HcmV?d00001