From 18c6a9e200cdec11f0e64c19edd2c1c358b7341a Mon Sep 17 00:00:00 2001 From: Gael Pasgrimaud Date: Fri, 17 Jun 2011 20:03:27 +0200 Subject: [PATCH] actions stuff --- buildout.cfg | 6 +- pyramid_formalchemy/actions.py | 155 +++++++++++++++ pyramid_formalchemy/views.py | 3 + .../pyramidapp/templates/foolisting.pt.py | 173 +++++++++++++++++ pyramidapp/pyramidapp/templates/fooshow.pt.py | 178 ++++++++++++++++++ setup.cfg | 1 + 6 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 pyramid_formalchemy/actions.py create mode 100644 pyramidapp/pyramidapp/templates/foolisting.pt.py create mode 100644 pyramidapp/pyramidapp/templates/fooshow.pt.py diff --git a/buildout.cfg b/buildout.cfg index 6e35e91..3362bd6 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -15,13 +15,15 @@ eggs = coverage PasteScript Sphinx + unittest2 + nose +scripts= + nosetests=tests [test] recipe = zc.recipe.egg eggs = ${eggs:eggs} - unittest2 - nose initialization = import os os.chdir(os.path.join('${buildout:directory}', 'pyramidapp')) diff --git a/pyramid_formalchemy/actions.py b/pyramid_formalchemy/actions.py new file mode 100644 index 0000000..4a97454 --- /dev/null +++ b/pyramid_formalchemy/actions.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +from chameleon.zpt.template import PageTemplate + + +class Action(object): + """A model action is used to add some action in model views:: + + >>> from webob import Request + >>> request = Request.blank('/') + + >>> class MyAction(Action): + ... body = u'' + + >>> action = MyAction('myaction', content=repr('Click here'), + ... attrs={'href': repr('#'), 'onclick': repr('$.click()')}) + >>> action.render(request) + u'Click here' + + """ + + def __init__(self, id, action='', content="", attrs=None, **rcontext): + self.id = id + self.attrs = attrs or {} + self.rcontext = rcontext + if 'id' not in self.attrs: + self.attrs['id'] = repr(id) + self.update() + attributes = u';'.join([u'%s %s' % v for v in self.attrs.items()]) + rcontext.update(attrs=self.attrs, attributes=attributes, id=id, content=content, action=action) + body = self.body % self.rcontext + self.template = PageTemplate(body) + + def update(self): + pass + + def render(self, request): + rcontext = {'action': self, 'request': request} + rcontext.update(self.rcontext) + return self.template.render(**rcontext) + +class Link(Action): + """ + An action rendered as a link:: + + >>> from webob import Request + >>> request = Request.blank('/') + >>> action = Link('myaction', content='label', + ... attrs={'href': 'request.application_url'}, + ... label='Click here') + >>> action.render(request) + u'Click here' + + """ + body = u'' + +class Input(Action): + """An action rendered as an input:: + + >>> from webob import Request + >>> request = Request.blank('/') + >>> action = Input('myaction', + ... value=repr('Click here')) + >>> action.render(request) + u'' + + """ + body = u'' + + def update(self): + if 'value' not in self.attrs: + self.attrs['value'] = repr(self.id.title()) + if 'type' not in self.attrs: + self.attrs['type'] = repr('submit') + +class UILink(Action): + """An action rendered as an jquery.ui aware link:: + + >>> from webob import Request + >>> request = Request.blank('/') + >>> action = UILink('myaction', icon='ui-icon-trash', + ... label='Click here') + >>> print action.render(request) + + + Click here + + + >>> action = UILink('myaction', icon='ui-icon-trash', + ... label='Click here', attrs={'onclick':'$(#link).click();'}) + >>> print action.render(request) + + + Click here + + """ + body = ''' + + + +''' + def update(self): + if 'state' not in self.rcontext: + self.rcontext['state'] = '' + if 'onclick' in self.attrs: + self.rcontext['onclick'] = self.attrs.pop('onclick') + self.attrs['onclick'] = 'onclick' + if 'href' not in self.attrs: + self.attrs['href'] = repr('#') + +save = UILink( + id='save', + label='Save', + icon='ui-icon-check', + attrs=dict(onclick="jQuery(this).parents('form').submit();"), + ) + +edit = UILink( + id='edit', + label='Edit', + icon='ui-icon-check', + attrs=dict(href="request.fa_url(request.model_name, request.model_id, 'edit')"), + ) + +delete = UILink( + id='delete', + views='edit', + label='Delete', + state='ui-state-error', + icon='ui-icon-trash', + attrs=dict(onclick=("string:var f = jQuery(this).parents('form');" + "f.attr('action', window.location.href.replace('/edit', '/delete'));" + "f.submit();")), + ) + +cancel = UILink( + id='cancel', + views='edit', + label='Cancel', + icon='ui-icon-circle-arrow-w', + attrs=dict(href="request.fa_url(request.model_name)"), + ) + +class Actions(list): + + def __init__(self, *args): + list.__init__(self, args) + + def render(self, request, **kwargs): + return u''.join([a.render(request, **kwargs) for a in self]) + +new_actions = Actions(save, cancel) +show_actions = Actions(edit, cancel) +edit_actions = Actions(save, delete, cancel) + diff --git a/pyramid_formalchemy/views.py b/pyramid_formalchemy/views.py index 31c96fb..ff68ca5 100644 --- a/pyramid_formalchemy/views.py +++ b/pyramid_formalchemy/views.py @@ -15,6 +15,7 @@ from pyramid import httpexceptions as exc from pyramid.exceptions import NotFound from pyramid_formalchemy.utils import TemplateEngine from pyramid_formalchemy import events +from pyramid_formalchemy import actions try: from formalchemy.ext.couchdb import Document @@ -117,6 +118,8 @@ class ModelView(object): def render(self, **kwargs): """render the form as html or json""" request = self.request + if 'action' in kwargs and request.format != 'json': + kwargs['actions'] = getattr(actions, '%(action)s_actions' % kwargs) if request.format != 'html': meth = getattr(self, 'render_%s_format' % request.format, None) if meth is not None: diff --git a/pyramidapp/pyramidapp/templates/foolisting.pt.py b/pyramidapp/pyramidapp/templates/foolisting.pt.py new file mode 100644 index 0000000..0c4e479 --- /dev/null +++ b/pyramidapp/pyramidapp/templates/foolisting.pt.py @@ -0,0 +1,173 @@ +registry = dict(version=0) +def bind(): + from cPickle import loads as _loads + _lookup_attr = _loads('cchameleon.core.codegen\nlookup_attr\np1\n.') + _init_scope = _loads('cchameleon.core.utils\necontext\np1\n.') + _attrs_4355972176 = _loads('(dp1\nVclass\np2\nVlayout-grid\np3\ns.') + _attrs_4355972112 = _loads('(dp1\nVclass\np2\nVui-pager\np3\ns.') + _attrs_4355971984 = _loads('(dp1\n.') + _init_stream = _loads('cchameleon.core.generation\ninitialize_stream\np1\n.') + _attrs_4355972496 = _loads('(dp1\nVclass\np2\nVui-icon ui-icon-circle-plus\np3\ns.') + _attrs_4355972240 = _loads('(dp1\n.') + _init_default = _loads('cchameleon.core.generation\ninitialize_default\np1\n.') + _re_amp = _loads("cre\n_compile\np1\n(S'&(?!([A-Za-z]+|#[0-9]+);)'\np2\nI0\ntRp3\n.") + _attrs_4355972368 = _loads('(dp1\nVclass\np2\nVui-widget-header ui-widget-link ui-corner-all\np3\ns.') + _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') + def render(econtext, rcontext=None): + macros = econtext.get('macros') + _translate = econtext.get('_translate') + _slots = econtext.get('_slots') + target_language = econtext.get('target_language') + u'_init_stream()' + (_out, _write, ) = _init_stream() + u'_init_tal()' + (_attributes, repeat, ) = _init_tal() + u'_init_default()' + _default = _init_default() + u'None' + default = None + u'None' + _domain = None + u"main.macros['master']" + _metal = _lookup_attr(econtext['main'], 'macros')['master'] + def _callback_main(econtext, _repeat, _out=_out, _write=_write, _domain=_domain, **_ignored): + if _repeat: + repeat.update(_repeat) + attrs = _attrs_4355971984 + u"''" + _write(u'
\n My Foo custom template\n ') + _default.value = default = '' + u'pager' + _content = econtext['pager'] + attrs = _attrs_4355972112 + u'_content' + _write(u'
') + _tmp1 = _content + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + _write(_tmp) + u"''" + _write(u'
\n ') + _default.value = default = '' + u'fs.render()' + _content = _lookup_attr(econtext['fs'], 'render')() + attrs = _attrs_4355972176 + u'_content' + _write(u'') + _tmp1 = _content + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + _write(_tmp) + _write(u'
\n ') + attrs = _attrs_4355972240 + _write(u'

\n ') + attrs = _attrs_4355972368 + u"request.fa_url(request.model_name, 'new')" + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' href="' + _tmp1) + '"')) + _write(u'>\n ') + attrs = _attrs_4355972496 + u"F_('New')" + _write(u'\n ') + _tmp1 = econtext['F_']('New') + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + if ('&' in _tmp): + if (';' in _tmp): + _tmp = _re_amp.sub('&', _tmp) + else: + _tmp = _tmp.replace('&', '&') + if ('<' in _tmp): + _tmp = _tmp.replace('<', '<') + if ('>' in _tmp): + _tmp = _tmp.replace('>', '>') + _write(_tmp) + u'model_name' + _write(u' ') + _tmp1 = econtext['model_name'] + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + if ('&' in _tmp): + if (';' in _tmp): + _tmp = _re_amp.sub('&', _tmp) + else: + _tmp = _tmp.replace('&', '&') + if ('<' in _tmp): + _tmp = _tmp.replace('<', '<') + if ('>' in _tmp): + _tmp = _tmp.replace('>', '>') + _write(_tmp) + _write(u'\n \n

\n
\n') + u"{'main': _callback_main}" + _tmp = {'main': _callback_main, } + u"main.macros['master']" + _metal.render(_tmp, _out=_out, _write=_write, _domain=_domain, econtext=econtext) + return _out.getvalue() + return render + +__filename__ = '/Users/gawel/py/formalchemy_project/pyramid_formalchemy/pyramidapp/pyramidapp/templates/foolisting.pt' +registry[(None, True, '1488bdb950901f8f258549439ef6661a49aae984')] = bind() diff --git a/pyramidapp/pyramidapp/templates/fooshow.pt.py b/pyramidapp/pyramidapp/templates/fooshow.pt.py new file mode 100644 index 0000000..342300b --- /dev/null +++ b/pyramidapp/pyramidapp/templates/fooshow.pt.py @@ -0,0 +1,178 @@ +registry = dict(version=0) +def bind(): + from cPickle import loads as _loads + _lookup_attr = _loads('cchameleon.core.codegen\nlookup_attr\np1\n.') + _init_scope = _loads('cchameleon.core.utils\necontext\np1\n.') + _re_amp = _loads("cre\n_compile\np1\n(S'&(?!([A-Za-z]+|#[0-9]+);)'\np2\nI0\ntRp3\n.") + _attrs_4356515344 = _loads('(dp1\n.') + _attrs_4356515728 = _loads('(dp1\nVclass\np2\nVui-widget-header ui-widget-link ui-corner-all\np3\ns.') + _attrs_4356515408 = _loads('(dp1\n.') + _init_stream = _loads('cchameleon.core.generation\ninitialize_stream\np1\n.') + _attrs_4356515920 = _loads('(dp1\nVclass\np2\nVui-icon ui-icon-circle-arrow-w\np3\ns.') + _attrs_4356515664 = _loads('(dp1\nVhref\np2\nV#\nsVclass\np3\nVui-widget-header ui-widget-link ui-widget-button ui-corner-all\np4\ns.') + _attrs_4356515216 = _loads('(dp1\n.') + _init_default = _loads('cchameleon.core.generation\ninitialize_default\np1\n.') + _attrs_4356515536 = _loads('(dp1\nVclass\np2\nVfa_field\np3\ns.') + _attrs_4356515792 = _loads("(dp1\nVtype\np2\nVsubmit\np3\nsVvalue\np4\nV${F_('Edit')}\np5\ns.") + _init_tal = _loads('cchameleon.core.generation\ninitialize_tal\np1\n.') + def render(econtext, rcontext=None): + macros = econtext.get('macros') + _translate = econtext.get('_translate') + _slots = econtext.get('_slots') + target_language = econtext.get('target_language') + u'_init_stream()' + (_out, _write, ) = _init_stream() + u'_init_tal()' + (_attributes, repeat, ) = _init_tal() + u'_init_default()' + _default = _init_default() + u'None' + default = None + u'None' + _domain = None + u"main.macros['master']" + _metal = _lookup_attr(econtext['main'], 'macros')['master'] + def _callback_main(econtext, _repeat, _out=_out, _write=_write, _domain=_domain, **_ignored): + if _repeat: + repeat.update(_repeat) + attrs = _attrs_4356515216 + u"''" + _write(u'
\n Custom Foo view\n ') + _default.value = default = '' + u'fs.render()' + _content = _lookup_attr(econtext['fs'], 'render')() + attrs = _attrs_4356515344 + u'_content' + _write(u'
') + _tmp1 = _content + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + _write(_tmp) + _write(u'
\n ') + attrs = _attrs_4356515408 + _write(u'
\n ') + attrs = _attrs_4356515536 + _write(u'

\n ') + attrs = _attrs_4356515664 + u"request.fa_url(request.model_name, request.model_id, 'edit')" + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' href="' + _tmp1) + '"')) + _write(u'>\n ') + attrs = _attrs_4356515792 + 'join(value("F_(\'Edit\')"),)' + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' value="' + _tmp1) + '"')) + _write(u' />\n \n ') + attrs = _attrs_4356515728 + u'request.fa_url(request.model_name)' + _write(u'' in _tmp1): + _tmp1 = _tmp1.replace('>', '>') + if ('"' in _tmp1): + _tmp1 = _tmp1.replace('"', '"') + _write(((' href="' + _tmp1) + '"')) + _write(u'>\n ') + attrs = _attrs_4356515920 + u"F_('Back')" + _write(u'\n ') + _tmp1 = econtext['F_']('Back') + _tmp = _tmp1 + if (_tmp.__class__ not in (str, unicode, int, float, )): + try: + _tmp = _tmp.__html__ + except: + _tmp = _translate(_tmp, domain=_domain, mapping=None, target_language=target_language, default=None) + else: + _tmp = _tmp() + _write(_tmp) + _tmp = None + if (_tmp is not None): + if not isinstance(_tmp, unicode): + _tmp = str(_tmp) + if ('&' in _tmp): + if (';' in _tmp): + _tmp = _re_amp.sub('&', _tmp) + else: + _tmp = _tmp.replace('&', '&') + if ('<' in _tmp): + _tmp = _tmp.replace('<', '<') + if ('>' in _tmp): + _tmp = _tmp.replace('>', '>') + _write(_tmp) + _write(u'\n \n

\n
\n
\n') + u"{'main': _callback_main}" + _tmp = {'main': _callback_main, } + u"main.macros['master']" + _metal.render(_tmp, _out=_out, _write=_write, _domain=_domain, econtext=econtext) + return _out.getvalue() + return render + +__filename__ = '/Users/gawel/py/formalchemy_project/pyramid_formalchemy/pyramidapp/pyramidapp/templates/fooshow.pt' +registry[(None, True, '1488bdb950901f8f258549439ef6661a49aae984')] = bind() diff --git a/setup.cfg b/setup.cfg index 74e2443..f404319 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,7 @@ match = ^test nocapture = 1 cover-package = pyramid_formalchemy with-coverage = 1 +with-doctest=true cover-erase = 1 [compile_catalog]