Net-ng/kansha

View on GitHub
kansha/card/view.py

Summary

Maintainability
A
3 hrs
Test Coverage
# -*- coding:utf-8 -*-
# --
# Copyright (c) 2012-2014 Net-ng.
# All rights reserved.
#
# This software is licensed under the BSD License, as described in
# the file LICENSE.txt, which you should have received as part of
# this distribution.
# --

from nagare.i18n import _
from nagare import ajax, component, presentation, security, var

from kansha import events

from .comp import Card, NewCard


@presentation.render_for(Card, 'no_dnd')
def render_card_no_dnd(self, h, comp, *args):
    """No DnD wrapping of the card"""
    return comp.render(h.AsyncRenderer())


@presentation.render_for(Card, 'new')
def render_card_new(self, h, comp, *args):
    h << comp.becomes(model=None)
    h << h.script(
        "card = YAHOO.util.Dom.get(%s);"
        "list = YAHOO.util.Dom.getAncestorByClassName(card, 'list-body');"
        "list.scrollTop = card.offsetTop - list.offsetTop;" %
        ajax.py2js(self.id)
    )
    return h.root


@presentation.render_for(Card)
def render(self, h, comp, *args):
    """Render the card"""

    extensions = self.extensions

    card_id = h.generate_id()

    onclick = h.a.action(self.emit_event, comp, events.CardClicked, comp).get('onclick').replace('return', "")
    with h.div(id=self.id, class_='card ' + self.card_filter(self)):
        with h.div(id=card_id, onclick=onclick):
            with h.div(class_='headers'):
                h << [extension.render(h, 'header') for _name, extension in extensions]
            with h.div(class_='covers'):
                with h.div(class_='title'):
                    h << self.title.render(h, 'readonly')
                h << [extension.render(h, 'cover') for _name, extension in extensions]
            with h.div(class_='badges'):
                h << [extension.render(h, 'badge') for _name, extension in extensions]
    if self.card_filter(self):
        h << component.Component(self.card_filter)

    h << h.script(
        "YAHOO.kansha.reload_cards[%s]=function() {%s}""" % (
            ajax.py2js(self.id),
            h.a.action(ajax.Update()).get('onclick')
        )
    )

    return h.root


@presentation.render_for(Card, model='readonly')
def render(self, h, comp, *args):
    """Render the card read-only"""
    with h.div(id=self.id, class_='card'):
        with h.div:
            with h.div(class_='title'):
                h << self.title.render(h, 'readonly')
            # FIXME: unify with main card view.
    return h.root


@presentation.render_for(Card, model='edit')
def render_card_edit(self, h, comp, *args):
    """Render card in edition mode"""
    # Test for delete card
    if self.data is None:
        return h.root

    parent_title = self.emit_event(comp, events.ParentTitleNeeded) or ''

    with h.div(class_='card-edit-form'):
        with h.div(class_='header'):
            with h.div(class_='title'):
                h << self.title.render(h.AsyncRenderer(), 0 if security.has_permissions('edit', self) else 'readonly')
                h << h.span('(%s)' % parent_title, class_='reminder')
        with h.div:
            with h.div(class_='card-actions'):
                h << comp.render(h, 'delete-action')
                h << [extension.render(h.AsyncRenderer(), 'action') for __, extension in self.extensions]
            with h.div(class_='card-edition'):
                for name, extension in self.extensions:
                    h << h.div(extension.render(h.AsyncRenderer()), class_=name)
        h << h.div(class_='clear')
    return h.root


@presentation.render_for(Card, 'delete-action')
def render_card_delete(self, h, comp, model):
    if security.has_permissions('edit', self) and not self.archived:
        with h.form:
            h << h.SyncRenderer().button(
                h.i(class_='icon-bin'),
                _('Delete'),
                onclick='return confirm(%s)' % ajax.py2js(
                    _(u'This card will be archived. Are you sure?')
                ).decode('UTF-8'),
                class_='btn delete').action(self.emit_event, comp, events.CardArchived)
    return h.root


@presentation.render_for(Card, 'calendar')
def render_in_calendar(self, h, comp, *args):
    # TODO should be in due_date extension
    due_date = dict(self.extensions)['due_date']().due_date
    if due_date:
        due_date = ajax.py2js(due_date, h)
        parent_title = self.emit_event(comp, events.ParentTitleNeeded) or ''
        card = u'{title:%s, editable:true, allDay: true, start: %s, _id: %s}' % (
            ajax.py2js(u'{} ({})'.format(self.data.title, parent_title), h).decode('utf-8'),
            due_date, ajax.py2js(self.id, h))
        clicked_cb = h.a.action(
            lambda: self.emit_event(comp, events.CardClicked, comp)
        ).get('onclick')

        dropped_cb = h.a.action(
            ajax.Update(
                action=self.card_dropped,
                render=lambda render: '',
                with_request=True
            )
        ).get('onclick')[:-2]

        h << h.script(u"""YAHOO.kansha.app.add_event($('#calendar'), %(card)s,
                         function() { %(clicked_cb)s},
                         function(start) { %(dropped_cb)s&start="+start);} )""" % {
            'card': card,
            'clicked_cb': clicked_cb,
            'dropped_cb': dropped_cb
        })

    return h.root


@presentation.render_for(Card, 'dnd')
def render_card_dnd(self, h, comp, *args):
    """DnD wrapping of the card"""
    if self.data is not None:
        id_ = h.generate_id('dnd')
        with h.div(id=id_, class_='card-dnd-wrapper'):
            h << comp.render(h.AsyncRenderer())
            h << h.script('YAHOO.kansha.dnd.initCard(%s)' % ajax.py2js(id_))
    return h.root


#####


@presentation.render_for(NewCard)
def render_new_card(self, h, comp, *args):
    """Render card creator minified"""
    h << h.a(h.strong('+'), h.span(_('Add a card')),
             class_='link-small').action(comp.becomes, model='add')
    if self.needs_refresh:
        h << h.script('increase_version();')
        self.toggle_refresh()
    return h.root


def toggle_answer(card_editor, comp, text):
    card_editor.toggle_refresh()
    comp.becomes(model=None)
    if text:
        comp.answer(text().strip())


@presentation.render_for(NewCard, 'add')
def render_new_card_add(self, h, comp, *args):
    """Render card creator form"""
    text = var.Var()
    id_ = h.generate_id('newCard')

    with h.form(class_='card-add-form'):
        h << h.input(type='text', id=id_).action(text)
        h << h.button(_('Add'), class_='btn btn-primary').action(toggle_answer, self, comp, text)
        h << ' '
        h << h.button(_('Cancel'), class_='btn').action(toggle_answer, self, comp, None)

    h << h.script("""document.getElementById(%s).focus(); """ % ajax.py2js(id_))

    return h.root