From: Thierry Parmentelat Date: Tue, 18 Dec 2012 15:07:37 +0000 (+0100) Subject: verticallayout as an elementary building plugin X-Git-Tag: myslice-django-0.1-1~132 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=ebd8f2a12cf7d63c735d4f7dc3f51620913fabfa;p=myslice.git verticallayout as an elementary building plugin --- diff --git a/engine/plugin.py b/engine/plugin.py index 85ae942d..4d6e4aab 100644 --- a/engine/plugin.py +++ b/engine/plugin.py @@ -10,14 +10,20 @@ class Plugin: uid=0 - def __init__ (self, **settings): + def __init__ (self, visible=True, hidable=True, hidden_by_default=False, **settings): + # xxx should generate some random id self.uuid=Plugin.uid Plugin.uid += 1 + self.visible=visible + self.hidable=hidable + self.hidden_by_default=hidden_by_default # we store as a dictionary the arguments passed to constructor - # e.g. SimpleList (visible=True) => _settings = {'visible':True} + # e.g. SimpleList (list=[1,2,3]) => _settings = { 'list':[1,2,3] } + # our own settings are not made part of _settings but could be.. self._settings=settings +# print "Created plugin with settings %s"%self._settings.keys() - def get_class (self): + def classname (self): try: return self.__class__.__name__ except: return 'Plugin' @@ -26,15 +32,15 @@ class Plugin: if setting not in self._settings: return default else: return self._settings[setting] - def is_visible (self): return self.get_setting ('visible',True) - def is_hidable (self): return self.get_setting ('hidable',False) - def is_hidden_by_default (self): return self.get_setting ('hidden_by_default', False) + def is_visible (self): return self.visible + def is_hidable (self): return self.hidable + def is_hidden_by_default (self): return self.hidden_by_default # returns the html code for that plugin # in essence, wraps the results of self.render_content () def render (self, request): uuid = self.uuid - title = self.get_class() + classname = self.classname() plugin_content = self.render_content (request) # expose _settings in json format to js @@ -45,22 +51,45 @@ class Plugin: # that gets passed to jquery somehow # see the bottom of result = render_to_string ('widget-plugin.html', - {'uuid':uuid, 'title':title, + {'uuid':uuid, 'classname':classname, 'visible':self.is_visible(), 'hidable':self.is_hidable(), 'hidden':self.is_hidden_by_default(), 'plugin_content' : plugin_content, - 'settings' : settings_json, + 'settings_json' : settings_json, }) return result - ### abstract interface # you may redefine this completely, but if you don't we'll just use method # template() to find out which template to use, and env() to find out which # dictionary to pass the templating system def render_content (self, request): """Should return an HTML fragment""" template = self.template() - env=self.env() - return render_to_string (template, env) + env=self.render_env(request) + if not isinstance (env,dict): + raise Exception, "%s.render_env returns wrong type"%self.classname() + env.update(self._settings) + result=render_to_string (template, env) + print "%s.render_content: BEG --------------------"%self.classname() + print "env=%s"%env.keys() + print result + print "%s.render_content: END --------------------"%self.classname() + return result + + def render_env (self, request): return {} + ######################################## abstract interface + + # your plugin is expected to implement either + # (*) def render_content(self, request) -> html fragment + # -- or -- + # (*) def template(self) -> filename + # (*) def render_env (self, request) -> dict + # this is the variable->value association used to render the template + # in which case the html template will be used + + def title (self): return "you should redefine title()" + + # tell the framework about requirements in the document header + def media_js (self): pass diff --git a/engine/views.py b/engine/views.py index 0f0309c9..0082a556 100644 --- a/engine/views.py +++ b/engine/views.py @@ -5,18 +5,20 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.shortcuts import render_to_response +from plugins.verticallayout import VerticalLayout from plugins.simplelist import SimpleList from myslice.viewutils import topmenu_items, the_user, hard_wired_slice_names def test_plugin_view (request): + # having html tags right here is not a real use case hard_wired_list=[] hard_wired_list.append("this hard-wired list") hard_wired_list.append("is defined") - hard_wired_list.append("in plugins.simplelist.py") + hard_wired_list.append("in plugins.simplelist.py") hard_wired_list.append("which in turn relies on") - hard_wired_list.append("template widget-template.html") + hard_wired_list.append("template widget-template.html") hard_wired_list.append("while it should of course") hard_wired_list.append("instead issue a query") hard_wired_list.append("and fill the DOM in js from there") @@ -27,12 +29,16 @@ def test_plugin_view (request): hard_wired_list.append("") hard_wired_list.append("OTOH and IMHO, there should be two separate and explicit subclasses of SimpleList for slices or testbeds") - plugin_main = SimpleList (visible=True, - hidable=True, - list=hard_wired_list, - header='Hard wired', - foo='the value for foo') - content_main = plugin_main.render (request) + plugin_main1 = SimpleList (list=hard_wired_list, + header='Hard wired', + foo='the value for foo') + plugin_main2 = SimpleList (hidable=True, + list=hard_wired_slice_names, + headers='Slices in main content') + layout = VerticalLayout (hidable=True, visible=True, + sons=[plugin_main1, plugin_main2] + ) + content_main = layout.render (request) # lacks a/href to /slice/%s plugin_related = SimpleList (visible=True, hidable=True, diff --git a/plugins/simplelist.py b/plugins/simplelist.py index 19abe28a..d08266b4 100644 --- a/plugins/simplelist.py +++ b/plugins/simplelist.py @@ -3,7 +3,12 @@ from django.template.loader import render_to_string from engine.plugin import Plugin class SimpleList (Plugin) : - - def render_content (self, request): - return render_to_string ("widget-simplelist.html", - self._settings) + + def template (self): return "simplelist.html" + + def media_js (): return [ 'js/simplelist.js' ] + + def media_css (): return { 'all': ('css/simplelist.css'), } + + # SimpleList is useless per se anyways + def title (self) : return "Title for Simple List" diff --git a/templates/widget-simplelist.html b/plugins/templates/simplelist.html similarity index 100% rename from templates/widget-simplelist.html rename to plugins/templates/simplelist.html diff --git a/plugins/templates/verticallayout.html b/plugins/templates/verticallayout.html new file mode 100644 index 00000000..4b77c94d --- /dev/null +++ b/plugins/templates/verticallayout.html @@ -0,0 +1,8 @@ +
+{% for son in sons %} +

{{ son.title }}

+
+{{ son.rendered }} +
+{% endfor %} +
diff --git a/plugins/verticallayout.py b/plugins/verticallayout.py new file mode 100644 index 00000000..61f6cab6 --- /dev/null +++ b/plugins/verticallayout.py @@ -0,0 +1,33 @@ +from django.template.loader import render_to_string + +from engine.plugin import Plugin + +class VerticalLayout (Plugin) : + + def __init__ (self, sons=[], *args, **kwds): + self.sons=sons + Plugin.__init__ (self, *args, **kwds) + + def insert (self, plugin): + self.sons.append(plugin) + + def title (self) : return "VLayout title" + + def render_env (self, request): + env = {} + sons_rendered = [ son.render(request) for son in self.sons ] + sons_titles = [ son.title() for son in self.sons ] + ids = range (len(self.sons)) + # for now we don't have a title to pass + sons = [ { 'id':id, 'rendered':rendered, 'title':title } + for id,rendered,title in zip (ids, sons_rendered, sons_titles) ] + env['sons']=sons + return env + + + def template (self): return "verticallayout.html" + + def media_js (): return [ 'js/simplelist.js' ] + + def media_css (): return { 'all': ('css/simplelist.css'), } + diff --git a/templates/widget-plugin.html b/templates/widget-plugin.html index 540cb4a6..20398015 100644 --- a/templates/widget-plugin.html +++ b/templates/widget-plugin.html @@ -2,51 +2,29 @@
{% if hidable %} {% if hidden %} -

» Show {{ title }}

- +

» Show {{ classname }}

+ {% else %} - -

« Hide {{ title }}

+ +

« Hide {{ classname }}

{% endif %} {% endif %} {% endif %} -
+
{{ plugin_content|safe }} -
+
{% if visible %}
{% endif %} +{# Plugin initialization (if the plugin has the right structure) - from plugin.php #} +{# note: that's the spirit but using {% insert %} is not reliable enough #} +{# so for now this doesn't make it back to the browser #} {% insert prelude_js %} -{% if visible and hidable %} -{# xxx sounds like this could be optimized by a single call performed on document.ready #} -{# that would do that on all DOM elements that require it #} - -/* Show / hide plugin */ -jQuery('#show_{{ uuid }}').click(function() { -jQuery('#{{ uuid }}').show(); -if (typeof jQuery('#{{ uuid }}').{{ title }} != 'undefined') { -jQuery('#{{ uuid }}').{{ title }}('show'); -}; -jQuery('#hide_{{ uuid }}').show(); -jQuery('#show_{{ uuid }}').hide(); -event.preventDefault(); -}); -jQuery('#hide_{{ uuid }}').click(function() { -jQuery('#{{ uuid }}').hide(); -jQuery('#hide_{{ uuid }}').hide(); -jQuery('#show_{{ uuid }}').show(); -event.preventDefault(); -}); -{% if hidden %} -jQuery('#{{ uuid }}').hide() -{% endif %} -{% endif %} -/* Plugin initialization (if the plugin has the right structure) - from plugin.php */ if (typeof jQuery('#{{ uuid }}').$title != 'undefined') { - jQuery('#{{ uuid }}').$title({ {{ settings }} plugin_uuid: '{{ uuid }}' }); + jQuery('#{{ uuid }}').$title({ {{ settings_json }} plugin_uuid: '{{ uuid }}' }); //jQuery('#{{ uuid }}').$title('show'); }; {% endinsert %}