web/views/timeline.py
changeset 10232 cda1bdc3652e
parent 9349 2519f8536b45
equal deleted inserted replaced
10231:fdcc500002ef 10232:cda1bdc3652e
     1 # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
    14 # details.
    14 # details.
    15 #
    15 #
    16 # You should have received a copy of the GNU Lesser General Public License along
    16 # You should have received a copy of the GNU Lesser General Public License along
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 """basic support for SIMILE's timeline widgets
       
    19 
    18 
    20 cf. http://code.google.com/p/simile-widgets/
    19 try:
    21 """
    20     from cubes.timeline.views import (
       
    21             TimelineJsonView,
       
    22             TimelineViewMixIn,
       
    23             TimelineView,
       
    24             StaticTimelineView)
    22 
    25 
    23 __docformat__ = "restructuredtext en"
    26 except ImportError:
       
    27     pass
       
    28 else:
       
    29     from logilab.common.deprecation import class_moved
    24 
    30 
    25 from logilab.mtconverter import xml_escape
    31     TimelineJsonView = class_moved(TimelineJsonView, 'TimelineJsonView')
    26 from logilab.common.date import ustrftime
    32     TimelineViewMixIn = class_moved(TimelineViewMixIn, 'TimelineViewMixIn')
    27 
    33     TimelineView = class_moved(TimelineView, 'TimelineView')
    28 from cubicweb.predicates import adaptable
    34     StaticTimelineView = class_moved(StaticTimelineView, 'StaticTimelineView')
    29 from cubicweb.view import EntityView, StartupView
       
    30 from cubicweb.utils import json_dumps
       
    31 
       
    32 _ = unicode
       
    33 
       
    34 class TimelineJsonView(EntityView):
       
    35     """generates a json file to feed Timeline.loadJSON()
       
    36     NOTE: work in progress (image_url, bubbleUrl and so on
       
    37     should be properties of entity classes or subviews)
       
    38     """
       
    39     __regid__ = 'timeline-json'
       
    40     __select__ = adaptable('ICalendarable')
       
    41 
       
    42     binary = True
       
    43     templatable = False
       
    44     content_type = 'application/json'
       
    45 
       
    46     date_fmt = '%Y/%m/%d'
       
    47 
       
    48     def call(self):
       
    49         events = []
       
    50         for entity in self.cw_rset.entities():
       
    51             event = self.build_event(entity)
       
    52             if event is not None:
       
    53                 events.append(event)
       
    54         timeline_data = {'dateTimeFormat': self.date_fmt,
       
    55                          'events': events}
       
    56         self.w(json_dumps(timeline_data))
       
    57 
       
    58     # FIXME: those properties should be defined by the entity class
       
    59     def onclick_url(self, entity):
       
    60         return entity.absolute_url()
       
    61 
       
    62     def onclick(self, entity):
       
    63         url = self.onclick_url(entity)
       
    64         if url:
       
    65             return u"javascript: document.location.href='%s'" % url
       
    66         return None
       
    67 
       
    68     def build_event(self, entity):
       
    69         """converts `entity` into a JSON object
       
    70         {'start': '1891',
       
    71         'end': '1915',
       
    72         'title': 'Portrait of Horace Brodsky',
       
    73         'description': 'by Henri Gaudier-Brzeska, French Sculptor, 1891-1915',
       
    74         'image': 'http://imagecache2.allposters.com/images/BRGPOD/102770_b.jpg',
       
    75         'link': 'http://www.allposters.com/-sp/Portrait-of-Horace-Brodsky-Posters_i1584413_.htm'
       
    76         }
       
    77         """
       
    78         icalendarable = entity.cw_adapt_to('ICalendarable')
       
    79         start = icalendarable.start
       
    80         stop = icalendarable.stop
       
    81         start = start or stop
       
    82         if start is None and stop is None:
       
    83             return None
       
    84         event_data = {'start': ustrftime(start, self.date_fmt),
       
    85                       'title': xml_escape(entity.dc_title()),
       
    86                       'description': entity.dc_description(format='text/html'),
       
    87                       'link': entity.absolute_url(),
       
    88                       }
       
    89         onclick = self.onclick(entity)
       
    90         if onclick:
       
    91             event_data['onclick'] = onclick
       
    92         if stop:
       
    93             event_data['end'] = ustrftime(stop, self.date_fmt)
       
    94         return event_data
       
    95 
       
    96 
       
    97 class TimelineViewMixIn(object):
       
    98     widget_class = 'TimelineWidget'
       
    99     jsfiles = ('cubicweb.timeline-bundle.js', 'cubicweb.widgets.js',
       
   100                'cubicweb.timeline-ext.js', 'cubicweb.ajax.js')
       
   101 
       
   102     def render_url(self, loadurl, tlunit=None):
       
   103         tlunit = tlunit or self._cw.form.get('tlunit')
       
   104         self._cw.add_js(self.jsfiles)
       
   105         self._cw.add_css('timeline-bundle.css')
       
   106         if tlunit:
       
   107             additional = u' cubicweb:tlunit="%s"' % tlunit
       
   108         else:
       
   109             additional = u''
       
   110         self.w(u'<div class="widget" cubicweb:wdgtype="%s" '
       
   111                u'cubicweb:loadtype="auto" cubicweb:loadurl="%s" %s >' %
       
   112                (self.widget_class, xml_escape(loadurl),
       
   113                 additional))
       
   114         self.w(u'</div>')
       
   115 
       
   116 
       
   117 class TimelineView(TimelineViewMixIn, EntityView):
       
   118     """builds a cubicweb timeline widget node"""
       
   119     __regid__ = 'timeline'
       
   120     title = _('timeline')
       
   121     __select__ = adaptable('ICalendarable')
       
   122     paginable = False
       
   123     def call(self, tlunit=None):
       
   124         self._cw.html_headers.define_var('Timeline_urlPrefix', self._cw.datadir_url)
       
   125         rql = self.cw_rset.printable_rql()
       
   126         loadurl = self._cw.build_url(rql=rql, vid='timeline-json')
       
   127         self.render_url(loadurl, tlunit)
       
   128 
       
   129 
       
   130 class StaticTimelineView(TimelineViewMixIn, StartupView):
       
   131     """similar to `TimelineView` but loads data from a static
       
   132     JSON file instead of one after a RQL query.
       
   133     """
       
   134     __regid__ = 'static-timeline'
       
   135 
       
   136     def call(self, loadurl, tlunit=None, wdgclass=None):
       
   137         self.widget_class = wdgclass or self.widget_class
       
   138         self.render_url(loadurl, tlunit)