Esempio n. 1
0
class MyosotisTimeline(timeline.TimelineView):
    __regid__ = 'myosotis.timeline'
    __select__ =  adaptable('ICalendarable')
    widget_class = 'MyosotisTimelineWidget'
    jsfiles = timeline.TimelineView.jsfiles + ('cubicweb.myosotis.js',)

    def render_url(self, loadurl, tlunit=None): # copied to avoid loadtype=auto
        tlunit = tlunit or self._cw.form.get('tlunit')
        self._cw.add_js(self.jsfiles)
        self._cw.add_css('timeline-bundle.css')
        if tlunit:
            additional = u' cubicweb:tlunit="%s"' % tlunit
        else:
            additional = u''
        self.w(u'<div class="widget" cubicweb:wdgtype="%s" '
               u'cubicweb:loadurl="%s" style="height:400px;" %s >' %
               (self.widget_class, xml_escape(loadurl),
                additional))
        self.w(u'</div>')

    def call(self, tlunit=None):
        super(MyosotisTimeline, self).call(tlunit)
        min_start_date = min(entity.cw_adapt_to('ICalendarable').start
                             for entity in self.cw_rset.entities())
        year, month, day = min_start_date.year, min_start_date.month-1, min_start_date.day
        self.w(u'<script type="text/javascript">jQuery(document).ready(function(){setMinVisibleDate(new Date(%d, %d, %d));});</script>' % (year, month, day))
Esempio n. 2
0
class RSSEntityFeedURL(Component):
    __regid__ = 'rss_feed_url'
    __select__ = one_line_rset() & adaptable('IFeed')

    def feed_url(self):
        entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
        return entity.cw_adapt_to('IFeed').rss_feed_url()
Esempio n. 3
0
class SetInitialStateHook(WorkflowHook):
    __regid__ = 'wfsetinitial'
    __select__ = WorkflowHook.__select__ & adaptable('IWorkflowable')
    events = ('after_add_entity', )

    def __call__(self):
        _SetInitialStateOp(self._cw, eid=self.entity.eid)
Esempio n. 4
0
class BaseTreeView(baseviews.ListView):
    """base tree view"""
    __regid__ = 'tree'
    __select__ = adaptable('ITree')
    item_vid = 'treeitem'

    def call(self, done=None, **kwargs):
        if done is None:
            done = set()
        super(BaseTreeView, self).call(done=done, **kwargs)

    def cell_call(self, row, col=0, vid=None, done=None, maxlevel=None, klass=None, **kwargs):
        assert maxlevel is None or maxlevel > 0
        done, entity = _done_init(done, self, row, col)
        if done is None:
            # entity is actually an error message
            self.w(u'<li class="badcontent">%s</li>' % entity)
            return
        self.open_item(entity)
        entity.view(vid or self.item_vid, w=self.w, **kwargs)
        if maxlevel is not None:
            maxlevel -= 1
            if maxlevel == 0:
                self.close_item(entity)
                return
        relatedrset = entity.cw_adapt_to('ITree').children(entities=False)
        self.wview(self.__regid__, relatedrset, 'null', done=done,
                   maxlevel=maxlevel, klass=klass, **kwargs)
        self.close_item(entity)

    def open_item(self, entity):
        self.w(u'<li class="%s">\n' % entity.cw_etype.lower())
    def close_item(self, entity):
        self.w(u'</li>\n')
Esempio n. 5
0
class hCalView(EntityView):
    """A calendar view that generates a hCalendar file

    Does apply to ICalendarable compatible entities
    """
    __regid__ = 'hcal'
    __select__ = adaptable('ICalendarable')
    paginable = False
    title = _('hCalendar')
    #templatable = False

    def call(self):
        self.w(u'<div class="hcalendar">')
        for i in range(len(self.cw_rset.rows)):
            task = self.cw_rset.complete_entity(i, 0)
            self.w(u'<div class="vevent">')
            self.w(u'<h3 class="summary">%s</h3>' % xml_escape(task.dc_title()))
            self.w(u'<div class="description">%s</div>'
                   % task.dc_description(format='text/html'))
            icalendarable = task.cw_adapt_to('ICalendarable')
            if icalendarable.start:
                self.w(u'<abbr class="dtstart" title="%s">%s</abbr>'
                       % (icalendarable.start.isoformat(),
                          self._cw.format_date(icalendarable.start)))
            if icalendarable.stop:
                self.w(u'<abbr class="dtstop" title="%s">%s</abbr>'
                       % (icalendarable.stop.isoformat(),
                          self._cw.format_date(icalendarable.stop)))
            self.w(u'</div>')
        self.w(u'</div>')
Esempio n. 6
0
class InContextWithStateView(EntityView):
    """display incontext view for an entity as well as its current state"""
    __regid__ = 'incontext-state'
    __select__ = adaptable('IWorkflowable')

    def entity_call(self, entity):
        iwf = entity.cw_adapt_to('IWorkflowable')
        self.w(u'%s [%s]' % (entity.view('incontext'), iwf.printable_state))
Esempio n. 7
0
 def test_etype_priority(self):
     with self.admin_access.web_request() as req:
         f = req.create_entity('FakeFile', data_name=u'hop.txt', data=Binary(b'hop'),
                               data_format=u'text/plain')
         rset = f.as_rset()
         anyscore = is_instance('Any')(f.__class__, req, rset=rset)
         idownscore = adaptable('IDownloadable')(f.__class__, req, rset=rset)
         self.assertTrue(idownscore > anyscore, (idownscore, anyscore))
         filescore = is_instance('FakeFile')(f.__class__, req, rset=rset)
         self.assertTrue(filescore > idownscore, (filescore, idownscore))
Esempio n. 8
0
class DownloadLinkView(EntityView):
    """view displaying a link to download the file"""
    __regid__ = 'downloadlink'
    __select__ = adaptable('IDownloadable')
    title = None  # should not be listed in possible views

    def cell_call(self, row, col, title=None, **kwargs):
        entity = self.cw_rset.get_entity(row, col)
        url = xml_escape(entity.cw_adapt_to('IDownloadable').download_url())
        self.w(u'<a href="%s">%s</a>' %
               (url, xml_escape(title or entity.dc_title())))
Esempio n. 9
0
 def test_multiple_entity_types_rset(self):
     class CWUserIWhatever(EntityAdapter):
         __regid__ = 'IWhatever'
         __select__ = is_instance('CWUser')
     class CWGroupIWhatever(EntityAdapter):
         __regid__ = 'IWhatever'
         __select__ = is_instance('CWGroup')
     with self.temporary_appobjects(CWUserIWhatever, CWGroupIWhatever):
         with self.admin_access.web_request() as req:
             selector = adaptable('IWhatever')
             rset = req.execute('Any X WHERE X is IN(CWGroup, CWUser)')
             self.assertTrue(selector(None, req, rset=rset))
Esempio n. 10
0
class MyosotisTimelineJson(timeline.TimelineJsonView):
    __select__ = adaptable('ICalendarable') & is_instance('Compte')
    colors = {u'trésorerie': 'gold',
              u'hôtel du comte': 'skyblue',
              u'hôtel de la comtesse': 'deeppink',
              u'compte de voyage': 'green',
              u'nul': 'grey',
              }
    def build_event(self, entity):
        event =  super(MyosotisTimelineJson, self).build_event(entity)
        event['color'] = self.colors.get(entity.type_compte.lower(), 'red')
        return event
Esempio n. 11
0
class IDownloadableOneLineView(baseviews.OneLineView):
    __select__ = adaptable('IDownloadable')

    def cell_call(self, row, col, title=None, **kwargs):
        """the oneline view is a link to download the file"""
        entity = self.cw_rset.get_entity(row, col)
        url = xml_escape(entity.absolute_url())
        adapter = entity.cw_adapt_to('IDownloadable')
        name = xml_escape(title or entity.dc_title())
        durl = xml_escape(adapter.download_url())
        self.w(u'<a href="%s">%s</a> [<a href="%s">%s</a>]' %
               (url, name, durl, self._cw._('download')))
Esempio n. 12
0
class IDownloadablePrimaryView(primary.PrimaryView):
    __select__ = adaptable('IDownloadable')

    def render_entity_attributes(self, entity):
        self.w(u'<div class="content">')
        adapter = entity.cw_adapt_to('IDownloadable')
        contenttype = adapter.download_content_type()
        if contenttype.startswith('image/'):
            self._cw.add_js('cubicweb.image.js')
            self.wview('image',
                       entity.cw_rset,
                       row=entity.cw_row,
                       col=entity.cw_col,
                       link=True,
                       klass='contentimage')
            super(IDownloadablePrimaryView,
                  self).render_entity_attributes(entity)
        elif contenttype.endswith('html'):
            self.wview('downloadlink',
                       entity.cw_rset,
                       title=self._cw._('download'),
                       row=entity.cw_row)
            self.wview('ehtml',
                       entity.cw_rset,
                       row=entity.cw_row,
                       col=entity.cw_col,
                       height='600px',
                       width='100%')
        else:
            super(IDownloadablePrimaryView,
                  self).render_entity_attributes(entity)
            self.wview('downloadlink',
                       entity.cw_rset,
                       title=self._cw._('download'),
                       row=entity.cw_row)
            self.render_data(entity, contenttype, 'text/html')
        self.w(u'</div>')

    def render_data(self, entity, sourcemt, targetmt):
        adapter = entity.cw_adapt_to('IDownloadable')
        if ENGINE.find_path(sourcemt, targetmt):
            try:
                self.w(
                    entity._cw_mtc_transform(adapter.download_data(), sourcemt,
                                             targetmt,
                                             adapter.download_encoding()))
            except Exception as ex:
                self.exception('while rendering data for %s', entity)
                msg = self._cw._("can't display data, unexpected error: %s") \
                      % xml_escape(unicode(ex))
                self.w('<div class="error">%s</div>' % msg)
            return True
        return False
Esempio n. 13
0
class BreadCrumbETypeVComponent(BreadCrumbEntityVComponent):
    __select__ = (basecomponents.HeaderComponent.__select__
                  & multi_lines_rset() & one_etype_rset()
                  & adaptable('IBreadCrumbs'))

    def render_breadcrumbs(self, w, contextentity, path):
        # XXX hack: only display etype name or first non entity path part
        root = path.pop(0)
        if isinstance(root, Entity):
            w(u'<a href="%s">%s</a>' %
              (self._cw.build_url(root.__regid__), root.dc_type('plural')))
        else:
            self.wpath_part(w, root, contextentity, not path)
Esempio n. 14
0
class ChangeStateFormView(form.FormViewMixIn, EntityView):
    __regid__ = 'statuschange'
    title = _('status change')
    __select__ = (one_line_rset()
                  & match_form_params('treid')
                  & adaptable('IWorkflowable'))

    def cell_call(self, row, col):
        entity = self.cw_rset.get_entity(row, col)
        transition = self._cw.entity_from_eid(self._cw.form['treid'])
        form = self.get_form(entity, transition)
        self.w(u'<h4>%s %s</h4>\n' %
               (self._cw._(transition.name), entity.view('oneline')))
        msg = self._cw._('status will change from %(st1)s to %(st2)s') % {
            'st1': entity.cw_adapt_to('IWorkflowable').printable_state,
            'st2': self._cw._(transition.destination(entity).name)
        }
        self.w(u'<p>%s</p>\n' % msg)
        form.render(w=self.w)

    def redirectpath(self, entity):
        return entity.rest_path()

    def get_form(self, entity, transition, **kwargs):
        # XXX used to specify both rset/row/col and entity in case implements
        # selector (and not is_instance) is used on custom form
        form = self._cw.vreg['forms'].select(
            'changestate',
            self._cw,
            entity=entity,
            transition=transition,
            redirect_path=self.redirectpath(entity),
            **kwargs)
        trinfo = self._cw.vreg['etypes'].etype_class('TrInfo')(self._cw)
        trinfo.eid = next(self._cw.varmaker)
        subform = self._cw.vreg['forms'].select('edition',
                                                self._cw,
                                                entity=trinfo,
                                                mainform=False)
        subform.field_by_name('wf_info_for', 'subject').value = entity.eid
        trfield = subform.field_by_name('by_transition', 'subject')
        trfield.widget = fwdgs.HiddenInput()
        trfield.value = transition.eid
        form.add_subform(subform)
        return form
Esempio n. 15
0
class DownloadBox(component.EntityCtxComponent):
    """add download box"""
    __regid__ = 'download_box'  # no download box for images
    __select__ = (component.EntityCtxComponent.__select__
                  & adaptable('IDownloadable') & ~has_mimetype('image/'))

    order = 10
    title = _('download')

    def init_rendering(self):
        self.items = [self.entity]

    def render_body(self, w):
        for item in self.items:
            idownloadable = item.cw_adapt_to('IDownloadable')
            w(u'<a href="%s"><img src="%s" alt="%s"/> %s</a>' %
              (xml_escape(idownloadable.download_url()),
               self._cw.uiprops['DOWNLOAD_ICON'], self._cw._('download icon'),
               xml_escape(idownloadable.download_file_name())))
Esempio n. 16
0
class DownloadView(EntityView):
    """download view

    this view is replacing the deprecated 'download' controller and allow
    downloading of entities providing the necessary interface
    """
    __regid__ = 'download'
    __select__ = one_line_rset() & adaptable('IDownloadable')

    templatable = False
    content_type = 'application/octet-stream'
    binary = True
    http_cache_manager = httpcache.EntityHTTPCacheManager
    add_to_breadcrumbs = False

    def set_request_content_type(self):
        """overriden to set the correct filetype and filename"""
        entity = self.cw_rset.complete_entity(self.cw_row or 0, self.cw_col
                                              or 0)
        adapter = entity.cw_adapt_to('IDownloadable')
        encoding = adapter.download_encoding()
        if encoding in BINARY_ENCODINGS:
            contenttype = 'application/%s' % encoding
            encoding = None
        else:
            contenttype = adapter.download_content_type()
        self._cw.set_content_type(contenttype or self.content_type,
                                  filename=adapter.download_file_name(),
                                  encoding=encoding,
                                  disposition='attachment')

    def call(self):
        entity = self.cw_rset.complete_entity(self.cw_row or 0, self.cw_col
                                              or 0)
        adapter = entity.cw_adapt_to('IDownloadable')
        self.w(adapter.download_data())

    def last_modified(self):
        return self.cw_rset.get_entity(self.cw_row or 0, self.cw_col
                                       or 0).modification_date
Esempio n. 17
0
class TreePathView(EntityView):
    """a recursive path view"""
    __regid__ = 'path'
    __select__ = adaptable('ITree')
    item_vid = 'oneline'
    separator = u'&#160;&gt;&#160;'

    def call(self, **kwargs):
        self.w(u'<div class="pathbar">')
        super(TreePathView, self).call(**kwargs)
        self.w(u'</div>')

    def cell_call(self, row, col=0, vid=None, done=None, **kwargs):
        done, entity = _done_init(done, self, row, col)
        if done is None:
            # entity is actually an error message
            self.w(u'<span class="badcontent">%s</span>' % entity)
            return
        parent = entity.cw_adapt_to('ITree').parent()
        if parent:
            parent.view(self.__regid__, w=self.w, done=done)
            self.w(self.separator)
        entity.view(vid or self.item_vid, w=self.w)
Esempio n. 18
0
    class iCalView(EntityView):
        """A calendar view that generates a iCalendar file (RFC 5545)

        Does apply to ICalendarable compatible entities
        """
        __select__ = adaptable('ICalendarable')
        paginable = False
        content_type = 'text/calendar'
        title = _('iCalendar')
        templatable = False
        __regid__ = 'ical'

        def call(self):
            ical = iCalendar()
            for i in range(len(self.cw_rset.rows)):
                task = self.cw_rset.complete_entity(i, 0)
                ical_task = task.cw_adapt_to('ICalendarable')
                if ical_task.component == ICAL_TODO:
                    elt = ical.add('vtodo')
                    stop_kw = "due"
                else:
                    elt = ical.add('vevent')
                    stop_kw = "dtend"
                elt.add('uid').value = task.absolute_url() # unique stable id
                elt.add('url').value = task.absolute_url()
                elt.add('summary').value = task.dc_title()
                elt.add('description').value = task.dc_description()
                if ical_task.start:
                    elt.add('dtstart').value = ical_task.start
                if ical_task.stop:
                    elt.add(stop_kw).value = ical_task.stop

            buff = ical.serialize()
            if not isinstance(buff, str):
                buff = str(buff, self._cw.encoding)
            self.w(buff)
Esempio n. 19
0
class NextPrevNavigationComponent(EntityCtxComponent):
    """Entities adaptable to the 'IPrevNext' should have this component
    automatically displayed. You may want to override this component to have a
    different look and feel.
    """

    __regid__ = 'prevnext'
    # register msg not generated since no entity implements IPrevNext in cubicweb
    # itself
    help = _('ctxcomponents_prevnext_description')
    __select__ = EntityCtxComponent.__select__ & adaptable('IPrevNext')
    context = 'navbottom'
    order = 10

    @property
    def prev_icon(self):
        return '<img src="%s" alt="%s" />' % (xml_escape(
            self._cw.data_url('go_prev.png')), self._cw._('previous page'))

    @property
    def next_icon(self):
        return '<img src="%s" alt="%s" />' % (xml_escape(
            self._cw.data_url('go_next.png')), self._cw._('next page'))

    def init_rendering(self):
        adapter = self.entity.cw_adapt_to('IPrevNext')
        self.previous = adapter.previous_entity()
        self.next = adapter.next_entity()
        if not (self.previous or self.next):
            raise EmptyComponent()

    def render_body(self, w):
        w(u'<div class="prevnext">')
        self.prevnext(w)
        w(u'</div>')
        w(u'<div class="clear"></div>')

    def prevnext(self, w):
        if self.previous:
            self.prevnext_entity(w, self.previous, 'prev')
        if self.next:
            self.prevnext_entity(w, self.next, 'next')

    def prevnext_entity(self, w, entity, type):
        textsize = self._cw.property_value('navigation.short-line-size')
        content = xml_escape(cut(entity.dc_title(), textsize))
        if type == 'prev':
            title = self._cw._('i18nprevnext_previous')
            icon = self.prev_icon
            cssclass = u'previousEntity left'
            content = icon + '&#160;&#160;' + content
        else:
            title = self._cw._('i18nprevnext_next')
            icon = self.next_icon
            cssclass = u'nextEntity right'
            content = content + '&#160;&#160;' + icon
        self.prevnext_div(w, type, cssclass, entity.absolute_url(), title,
                          content)

    def prevnext_div(self, w, type, cssclass, url, title, content):
        w(u'<div class="%s">' % cssclass)
        w(u'<a href="%s" title="%s">%s</a>' %
          (xml_escape(url), xml_escape(title), content))
        w(u'</div>')
        self._cw.html_headers.add_raw('<link rel="%s" href="%s" />' %
                                      (type, xml_escape(url)))
Esempio n. 20
0
class BreadCrumbEntityVComponent(basecomponents.HeaderComponent):
    __regid__ = 'breadcrumbs'
    __select__ = (basecomponents.HeaderComponent.__select__
                  & one_line_rset() & adaptable('IBreadCrumbs'))
    order = basecomponents.ApplicationName.order + 1
    context = basecomponents.ApplicationName.context
    separator = u'&#160;&gt;&#160;'
    link_template = u'<a href="%s">%s</a>'
    first_separator = True

    # XXX support kwargs for compat with other components which gets the view as
    # argument
    def render(self, w, **kwargs):
        try:
            entity = self.cw_extra_kwargs['entity']
        except KeyError:
            entity = self.cw_rset.get_entity(0, 0)
        adapter = entity.cw_adapt_to('IBreadCrumbs')
        view = self.cw_extra_kwargs.get('view')
        path = adapter.breadcrumbs(view)
        if path:
            self.open_breadcrumbs(w)
            self.render_breadcrumbs(w, entity, path)
            self.close_breadcrumbs(w)

    def open_breadcrumbs(self, w):
        w(u'<span id="breadcrumbs" class="pathbar">')
        if self.first_separator:
            w(self.separator)

    def close_breadcrumbs(self, w):
        w(u'</span>')

    def render_root(self, w, contextentity, path):
        root = path.pop(0)
        if isinstance(root, Entity):
            w(self.link_template %
              (self._cw.build_url(root.__regid__), root.dc_type('plural')))
            w(self.separator)
        self.wpath_part(w, root, contextentity, not path)

    def render_breadcrumbs(self, w, contextentity, path):
        self.render_root(w, contextentity, path)
        for i, parent in enumerate(path):
            w(self.separator)
            w(u"\n")
            self.wpath_part(w, parent, contextentity, i == len(path) - 1)

    def wpath_part(self,
                   w,
                   part,
                   contextentity,
                   last=False):  # XXX deprecates last argument?
        if isinstance(part, Entity):
            w(part.view('breadcrumbs'))
        elif isinstance(part, tuple):
            url, title = part
            textsize = self._cw.property_value('navigation.short-line-size')
            w(self.link_template %
              (xml_escape(url), xml_escape(uilib.cut(title, textsize))))
        else:
            textsize = self._cw.property_value('navigation.short-line-size')
            w(xml_escape(uilib.cut(str(part), textsize)))
Esempio n. 21
0
class TimeTableView(EntityView):
    __regid__ = 'timetable'
    title = _('timetable')
    __select__ = adaptable('ICalendarable')
    paginable = False

    def call(self, title=None):
        """Dumps a timetable from a resultset composed of a note (anything
        with start/stop) and a user (anything)"""
        self._cw.add_css('cubicweb.timetable.css')
        dates = {}
        users = []
        users_max = {}
        # XXX: try refactoring with calendar.py:OneMonthCal
        for row in range(self.cw_rset.rowcount):
            task = self.cw_rset.get_entity(row, 0)
            icalendarable = task.cw_adapt_to('ICalendarable')
            if len(self.cw_rset[row]
                   ) > 1 and self.cw_rset.description[row][1] == 'CWUser':
                user = self.cw_rset.get_entity(row, 1)
            else:
                user = ALL_USERS
            the_dates = []
            if icalendarable.start and icalendarable.stop:
                if icalendarable.start.toordinal(
                ) == icalendarable.stop.toordinal():
                    the_dates.append(icalendarable.start)
                else:
                    the_dates += date_range(icalendarable.start,
                                            icalendarable.stop + ONEDAY)
            elif icalendarable.start:
                the_dates.append(icalendarable.start)
            elif icalendarable.stop:
                the_dates.append(icalendarable.stop)
            for d in the_dates:
                d = todatetime(d)
                d_users = dates.setdefault(d, {})
                u_tasks = d_users.setdefault(user, set())
                u_tasks.add(task)
                task_max = users_max.setdefault(user, 0)
                if len(u_tasks) > task_max:
                    users_max[user] = len(u_tasks)
            if user not in users:
                # keep original ordering
                users.append(user)
        if not dates:
            return
        date_min = min(dates)
        date_max = max(dates)
        #users = list(sorted(users, key=lambda u:u.login))

        rows = []
        # colors here are class names defined in cubicweb.css
        colors = ["col%x" % i for i in range(12)]
        next_color_index = 0

        visited_tasks = {}  # holds a description of a task for a user
        task_colors = {}  # remember a color assigned to a task
        for date in date_range(date_min, date_max + ONEDAY):
            columns = [date]
            d_users = dates.get(date, {})
            for user in users:
                # every user has its column "splitted" in at least MIN_COLS
                # sub-columns (for overlapping tasks)
                user_columns = [None] * max(MIN_COLS, users_max[user])
                # every task that is "visited" for the first time
                # require a special treatment, so we put them in
                # 'postpone'
                postpone = []
                for task in d_users.get(user, []):
                    key = (task, user)
                    if key in visited_tasks:
                        task_descr = visited_tasks[key]
                        user_columns[task_descr.column] = task_descr, False
                        task_descr.lines += 1
                    else:
                        postpone.append(key)
                for key in postpone:
                    # to every 'new' task we must affect a color
                    # (which must be the same for every user concerned
                    # by the task)
                    task, user = key
                    for i, t in enumerate(user_columns):
                        if t is None:
                            if task in task_colors:
                                color = task_colors[task]
                            else:
                                color = colors[next_color_index]
                                next_color_index = (next_color_index +
                                                    1) % len(colors)
                                task_colors[task] = color
                            task_descr = _TaskEntry(task, color, i)
                            user_columns[i] = task_descr, True
                            visited_tasks[key] = task_descr
                            break
                    else:
                        raise RuntimeError("is it possible we got it wrong?")

                columns.append(user_columns)
            rows.append(columns)

        widths = [len(col) for col in rows[0][1:]]
        self.w(u'<div class="section">')
        if title:
            self.w(u'<h4>%s</h4>\n' % title)
        self.w(u'<table class="listing timetable">')
        self.render_col_headers(users, widths)
        self.render_rows(rows)
        self.w(u'</table>')
        self.w(u'</div>\n')

    def render_col_headers(self, users, widths):
        """ render column headers """
        self.w(u'<tr class="header">\n')

        self.w(u'<th class="ttdate">&#160;</th>\n')
        columns = []
        for user, width in zip(users, widths):
            self.w(u'<th colspan="%s">' % max(MIN_COLS, width))
            if user is ALL_USERS:
                self.w(u'*')
            else:
                user.view('oneline', w=self.w)
            self.w(u'</th>')
        self.w(u'</tr>\n')
        return columns

    def render_rows(self, rows):
        """ render table content (row headers and central content) """
        odd = False
        previous_is_empty = False
        for row in rows:
            date = row[0]
            empty_line = True
            for group in row[1:]:
                for value in group:
                    if value:
                        empty_line = False
                        break
                else:
                    continue
                break
            if empty_line and previous_is_empty:
                continue
            previous_is_empty = False

            klass = "even"
            if date.weekday() in (5, 6) and not empty_line:
                klass = "odd"
            self.w(u'<tr class="%s">' % klass)
            odd = not odd

            if not empty_line:
                self.w(u'<th class="ttdate">%s</th>' %
                       self._cw.format_date(date))
            else:
                self.w(u'<th>...</th>')
                previous_is_empty = True

            empty_klasses = ["ttle", "ttme", "ttre"]
            filled_klasses = ["ttlf", "ttmf", "ttrf"]
            kj = 0  # 0: left, 1: mid, 2: right
            for uid, group in enumerate(row[1:]):
                for i, value in enumerate(group):
                    if i == 0:
                        kj = 0
                    elif i == len(group):
                        kj = 2
                    else:
                        kj = 1
                    if value:
                        task_descr, first_row = value
                        if first_row:
                            url = xml_escape(
                                task_descr.task.absolute_url(vid="edition"))
                            self.w(
                                u'<td rowspan="%d" class="%s %s" onclick="document.location=\'%s\'">&#160;<div>'
                                % (task_descr.lines, task_descr.color,
                                   filled_klasses[kj], url))
                            task_descr.task.view('tooltip', w=self.w)
                            self.w(u'</div></td>')
                    else:
                        if empty_line:
                            self.w(u'<td class="ttempty">&#160;</td>')
                        else:
                            self.w(u'<td class="%s">&#160;</td>' %
                                   empty_klasses[kj])
            self.w(u'</tr>\n')
Esempio n. 22
0
class CalendarView(EntityView):
    __regid__ = 'calendar'
    __select__ = adaptable('ICalendarable')

    paginable = False
    title = _('calendar')

    fullcalendar_options = {
        'firstDay': 1,
        'firstHour': 8,
        'defaultView': 'month',
        'editable': True,
        'header': {'left': 'prev,next today',
                   'center': 'title',
                   'right': 'month,agendaWeek,agendaDay',
                   },
        }

    def call(self, cssclass=""):
        self._cw.add_css(('fullcalendar.css', 'cubicweb.calendar.css'))
        self._cw.add_js(('jquery.ui.js', 'fullcalendar.min.js', 'jquery.qtip.min.js', 'fullcalendar.locale.js'))
        self.calendar_id = 'cal' + make_uid('uid')
        self.add_onload()
        # write calendar div to load jquery fullcalendar object
        if cssclass:
            self.w(u'<div class="%s" id="%s"></div>' % (cssclass, self.calendar_id))
        else:
            self.w(u'<div id="%s"></div>' % self.calendar_id)

    def add_onload(self):
        fullcalendar_options = self.fullcalendar_options.copy()
        fullcalendar_options['events'] = self.get_events()
        # i18n
        # js callback to add a tooltip and to put html in event's title
        js = """
        var options = $.fullCalendar.regional('%s', %s);
        options.eventRender = function(event, $element) {
          // add a tooltip for each event
          var div = '<div class="tooltip">'+ event.description+ '</div>';
          $element.append(div);
          // allow to have html tags in event's title
          $element.find('span.fc-event-title').html($element.find('span.fc-event-title').text());
        };
        $("#%s").fullCalendar(options);
        """ #"
        self._cw.add_onload(js % (self._cw.lang, json_dumps(fullcalendar_options), self.calendar_id))

    def get_events(self):
        events = []
        for entity in self.cw_rset.entities():
            icalendarable = entity.cw_adapt_to('ICalendarable')
            if not (icalendarable.start and icalendarable.stop):
                continue
            start_date = icalendarable.start or  icalendarable.stop
            event = {'eid': entity.eid,
                     'title': entity.view('calendaritem'),
                     'url': xml_escape(entity.absolute_url()),
                     'className': 'calevent',
                     'description': entity.view('tooltip'),
                     }
            event['start'] = start_date.strftime('%Y-%m-%dT%H:%M')
            event['allDay'] = True
            if icalendarable.stop:
                event['end'] = icalendarable.stop.strftime('%Y-%m-%dT%H:%M')
                event['allDay'] = False
            events.append(event)
        return events
Esempio n. 23
0
class TreeViewItemView(EntityView):
    """specific treeitem view for entities which adapt to ITree

    (each item should be expandable if it's not a tree leaf)
    """
    __regid__ = 'treeitemview'
    __select__ = adaptable('ITree')
    default_branch_state_is_open = False

    def open_state(self, eeid, treeid):
        cookies = self._cw.get_cookie()
        treestate = cookies.get(treecookiename(treeid))
        if treestate:
            return str(eeid) in treestate.value.split(':')
        return self.default_branch_state_is_open

    def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview',
                  is_last=False, **morekwargs):
        w = self.w
        entity = self.cw_rset.get_entity(row, col)
        itree = entity.cw_adapt_to('ITree')
        liclasses = []
        if self._cw.url(includeparams=False) == entity.absolute_url():
            liclasses.append(u'selected')
        is_open = self.open_state(entity.eid, treeid)
        is_leaf = itree is None or itree.is_leaf()
        if is_leaf:
            if is_last:
                liclasses.append('last')
            w(u'<li class="%s">' % u' '.join(liclasses))
        else:
            rql = itree.children_rql() % {'x': entity.eid}
            url = xml_escape(self._cw.build_url('ajax', rql=rql, vid=parentvid,
                                                pageid=self._cw.pageid,
                                                treeid=treeid,
                                                fname='view',
                                                treesubvid=vid,
                                                morekwargs=json.dumps(morekwargs)))
            divclasses = ['hitarea']
            if is_open:
                liclasses.append('collapsable')
                divclasses.append('collapsable-hitarea')
            else:
                liclasses.append('expandable')
                divclasses.append('expandable-hitarea')
            if is_last:
                if is_open:
                    liclasses.append('lastCollapsable')
                    divclasses.append('lastCollapsable-hitarea')
                else:
                    liclasses.append('lastExpandable')
                    divclasses.append('lastExpandable-hitarea')
            if is_open:
                w(u'<li class="%s">' % u' '.join(liclasses))
            else:
                w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
            if treeid.startswith('throw_away'):
                divtail = ''
            else:
                divtail = """ onclick="asyncRemoteExec('node_clicked', '%s', '%s')" """ % (
                    treeid, entity.eid)
            w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))

            # add empty <ul> because jquery's treeview plugin checks for
            # sublists presence
            if not is_open:
                w(u'<ul class="placeholder"><li>place holder</li></ul>')
        # the local node info
        self.wview(vid, self.cw_rset, row=row, col=col, **morekwargs)
        if is_open and not is_leaf: #  => rql is defined
            self.wview(parentvid, itree.children(entities=False), subvid=vid,
                       treeid=treeid, initial_load=False, **morekwargs)
        w(u'</li>')