verticallayout as an elementary building plugin
authorThierry Parmentelat <thierry.parmentelat@inria.fr>
Tue, 18 Dec 2012 15:07:37 +0000 (16:07 +0100)
committerThierry Parmentelat <thierry.parmentelat@inria.fr>
Tue, 18 Dec 2012 15:07:37 +0000 (16:07 +0100)
engine/plugin.py
engine/views.py
plugins/simplelist.py
plugins/templates/simplelist.html [moved from templates/widget-simplelist.html with 100% similarity]
plugins/templates/verticallayout.html [new file with mode: 0644]
plugins/verticallayout.py [new file with mode: 0644]
templates/widget-plugin.html

index 85ae942..4d6e4aa 100644 (file)
@@ -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
index 0f0309c..0082a55 100644 (file)
@@ -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 <code>plugins.simplelist.py</code>")
+    hard_wired_list.append("in plugins.simplelist.py")
     hard_wired_list.append("which in turn relies on")
-    hard_wired_list.append("template <code>widget-template.html</code>")
+    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,
index 19abe28..d08266b 100644 (file)
@@ -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/plugins/templates/verticallayout.html b/plugins/templates/verticallayout.html
new file mode 100644 (file)
index 0000000..4b77c94
--- /dev/null
@@ -0,0 +1,8 @@
+<div id='{{ uuid }}'>
+{% for son in sons %}
+<h3>{{ son.title }}</h3>
+<div id='{{ uuid }}-{{ son.id }}'>
+{{ son.rendered }}
+</div>
+{% endfor %}
+</div>
diff --git a/plugins/verticallayout.py b/plugins/verticallayout.py
new file mode 100644 (file)
index 0000000..61f6cab
--- /dev/null
@@ -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'), }
+
index 540cb4a..2039801 100644 (file)
@@ -2,51 +2,29 @@
 <div class='plugin-manage'>
 {% if hidable %}
   {% if hidden %}
-<p id='show-{{ uuid }}' class='plugin-show'><a href='#'><span>&raquo; Show {{ title }}</span></a></p>
-<p id='hide-{{ uuid }}' class='plugin-hide' style='display:none;'><a href='#'><span>&laquo; Hide {{ title }}</span></a></p>
+<p id='show-{{ uuid }}' class='plugin-show'><a href='#'><span>&raquo; Show {{ classname }}</span></a></p>
+<p id='hide-{{ uuid }}' class='plugin-hide' style='display:none;'><a href='#'><span>&laquo; Hide {{ classname }}</span></a></p>
   {% else %}
-<p id='show-{{ uuid }}' class='plugin-show' style='display:none;'><a href='#'><span>&raquo; Show {{ title }}</span></a></p>
-<p id='hide-{{ uuid }}' class='plugin-hide'><a href='#'><span>&laquo; Hide {{ title }}</span></a></p>
+<p id='show-{{ uuid }}' class='plugin-show' style='display:none;'><a href='#'><span>&raquo; Show {{ classname }}</span></a></p>
+<p id='hide-{{ uuid }}' class='plugin-hide'><a href='#'><span>&laquo; Hide {{ classname }}</span></a></p>
   {% endif %}
 {% endif %}
 {% endif %}
 
-<div class='plugin {{ title }}' id='plugin-{{ uuid }}'>
+<div class='plugin {{ classname }}' id='plugin-{{ uuid }}'>
 {{ plugin_content|safe }}
-</div><!--plugin {{ title }}-->
+</div><!--plugin {{ classname }}-->
 
 {% if visible %}
 </div>
 {% 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 %}