[Ovirt-devel] [PATCH server] Stage of one of tree conversions to pluggable widget.

Jason Guiditta jguiditt at redhat.com
Thu Oct 23 21:24:35 UTC 2008


This patch includes the new pluggable tree widget code and
conversion of Move popups for Hardware pools (hosts and
storage).  Simplified call to move so it returns an object
which is used to build the tree (no extra ajax call anymore).
The json_tree_internal method will be going away next patch,
can't get rid of it yet because some Smart Pool stuff depends
on it.

Fixed minor bug in Pool.full_set_nested causing 'selected'
never to be set. Also added to this method a 'type' option
to filter results by pool type.

Signed-off-by: Jason Guiditta <jguiditt at redhat.com>
---
 src/app/controllers/hardware_controller.rb |    4 ++
 src/app/models/pool.rb                     |    7 +++-
 src/app/views/hardware/move.rhtml          |   60 +++++++++++++++-----------
 src/app/views/layouts/_tree.rhtml          |    9 +---
 src/app/views/layouts/redux.rhtml          |    3 +
 src/public/javascripts/ovirt.tree.js       |   64 +++++++++++++++++++++++++++-
 src/public/stylesheets/ovirt-tree/tree.css |    7 +++-
 7 files changed, 119 insertions(+), 35 deletions(-)

diff --git a/src/app/controllers/hardware_controller.rb b/src/app/controllers/hardware_controller.rb
index 9c04210..4f24cb3 100644
--- a/src/app/controllers/hardware_controller.rb
+++ b/src/app/controllers/hardware_controller.rb
@@ -184,6 +184,10 @@ class HardwareController < PoolController
   def move
     pre_modify
     @resource_type = params[:resource_type]
+    @id = params[:id]
+    @pools = HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element,
+                       :privilege => Permission::PRIV_MODIFY, :user => get_login_user, :current_id => @id,
+                       :type => :select_hardware_pools).to_json
     render :layout => 'popup'
   end
 
diff --git a/src/app/models/pool.rb b/src/app/models/pool.rb
index d189649..a8b1589 100644
--- a/src/app/models/pool.rb
+++ b/src/app/models/pool.rb
@@ -230,6 +230,7 @@ class Pool < ActiveRecord::Base
     method = opts.delete(:method) {:hash_element}
     privilege = opts.delete(:privilege)
     user = opts.delete(:user)
+    type = opts.delete(:type)
     smart_pool_set = opts.delete(:smart_pool_set)
     if privilege and user
       opts[:include] = "permissions"
@@ -241,6 +242,7 @@ class Pool < ActiveRecord::Base
     opts.delete(:order)
     subtree_list = full_set(opts)
     subtree_list -= [self] if smart_pool_set
+    subtree_list = Pool.send(type, subtree_list) if type
     return_tree_list = []
     ref_hash = {}
     subtree_list.each do |pool|
@@ -264,7 +266,10 @@ class Pool < ActiveRecord::Base
         end
       end
     end
-    ref_hash[current_id][:selected] = true if current_id
+#   FIXME: right now, we have inserted the pool id into the hash as an
+#   integer (database value type.  Rather than converting the current_id
+#   param to an integer, we may want to use a symbol for both identifiers
+    ref_hash[current_id.to_i][:selected] = true if current_id
     return_tree_list
   end
 
diff --git a/src/app/views/hardware/move.rhtml b/src/app/views/hardware/move.rhtml
index 968e2ca..9688c39 100644
--- a/src/app/views/hardware/move.rhtml
+++ b/src/app/views/hardware/move.rhtml
@@ -6,21 +6,15 @@
 <%- end -%>
 
 <script type="text/javascript">
-      $(document).ready(function(){         
-        $("#move_tree").asynch_treeview({
-            //animated: "normal",
-            current_pool_id:  <%=@current_pool_id%>,
-            url: "<%=  url_for :controller =>'/hardware', :action => 'json_move_tree' %>",
-            current: "disabled",
-            hardware_url: "#",
-            resource_url: "#",
-            onclick: "move_<%= @resource_type %>",
-            action_type: "javascript"
-	    })
-	}); 
-  function move_<%= @resource_type %>(target_pool_id)
-  {
-    $.post('<%= url_for :controller => "hardware", :action => "move_#{@resource_type}", :id => @pool %>',
+      $(document).ready(function(){
+        $('#move_tree').tree({
+          content: {"pools" : <%=  @pools %>},
+          clickHandler: move_<%= @resource_type %>
+        });
+      });
+  function move_<%= @resource_type %>(e, elem) {
+    var target_pool_id = elem.id.substring(elem.id.indexOf('-') +1);
+    $.post('<%= url_for :controller => "hardware", :action => "move_#{@resource_type}", :id => @id %>',
            { resource_ids: get_selected_<%= @resource_type %>().toString(), 
 	     target_pool_id: target_pool_id },
             function(data,status){
@@ -37,24 +31,38 @@
 $('#move_to_new_pool').click(function(){
 		$('#window').fadeOut('fast'); 
         $("#window").empty().load("<%= url_for :controller => 'hardware', :action => 'new' %>",
-	{ parent_id: <%=@pool.id%>, 
+	{ parent_id: <%=@id%>,
 	  resource_ids: get_selected_<%= @resource_type %>().toString(),
           resource_type: '<%=@resource_type%>'});
 		$('#window').fadeIn('fast'); 
 });
 </script>
+<ul id="move_tree" class="ovirt-tree"></ul>
 
+<textarea id="tree_template" style="display:none;">
+{macro htmlList(list, optionalListType)}
+  {var listType = optionalListType != null ? optionalListType : "ul"}
+  <${listType} style="display:none;">
+    {for item in list}
+      <li>
+        <span class="hitarea {if item.children} expandable{/if}"> </span><div id="move-${item.id}" class="${item.type} {if item.selected} unclickable{/if}">${item.name}</div>
+        {if item.children}
+          ${htmlList(item.children)}
+        {/if}
+      </li>
+    {/for}
+  </${listType}>
+{/macro}
 
-
-<div class="dialog_tree">
-  <ul id="move_tree" class="filetree treeview-famfamfam treeview"></ul>
-
-  <!--  <div style="clear:both;"></div>
-  <div style=" float:left; padding:0 0 0 5px;"><%= image_tag "icon_unassignedhost.gif" %></div>
-  <div style=" float:left; padding:5px 0 0 5px;">Unassigned Hosts</div>-->
-</div>
-
-
+{for item in pools}
+  <li>
+    <span class="hitarea {if item.children} expandable{/if}"> </span><div id="move-${item.id}" class="${item.type} {if item.selected} unclickable{/if}">${item.name}</div>
+    {if item.children}
+      ${htmlList(item.children)}
+    {/if}
+  </li>
+{/for}
+</textarea>
 
 <div class="facebox_timfooter">
         <div class="button">
diff --git a/src/app/views/layouts/_tree.rhtml b/src/app/views/layouts/_tree.rhtml
index a6bde14..fefd642 100644
--- a/src/app/views/layouts/_tree.rhtml
+++ b/src/app/views/layouts/_tree.rhtml
@@ -1,6 +1,3 @@
-<%= javascript_include_tag "trimpath-template-1.0.38.js" %>
-<%= javascript_include_tag "ovirt.tree.js" %>
-<%= stylesheet_link_tag 'ovirt-tree/tree' %>
 <script type="text/javascript">
     var treeTimer, urlObj;
     var processRecursive = true;
@@ -17,12 +14,12 @@
       tree_url = "<%=  url_for :controller =>"/tree", :action => "return_filtered_list" %>";
       processTree();
       treeTimer = setInterval(processTree,15000);
-      $('ul.ovirt-tree li').livequery(
+      $('#nav_tree_form ul.ovirt-tree li').livequery(
         function(){
           $(this)
           .children('div')
           .bind('click',function(){
-            $('ul.ovirt-tree li div').removeClass('current');
+            $('#nav_tree_form ul.ovirt-tree li div').removeClass('current');
             var thisHref = (urlObj[$(this).attr('class')] !=null) ? urlObj[$(this).attr('class')] + '/' + this.id :null;
             $(this).toggleClass('current');
             currentNode = this.id;
@@ -50,7 +47,7 @@
           .unbind('click');
         }
       );
-      $('ul.ovirt-tree li:has(ul)').livequery(
+      $('#nav_tree_form ul.ovirt-tree li:has(ul)').livequery(
         function(){
           $(this)
             .children('span.hitarea')
diff --git a/src/app/views/layouts/redux.rhtml b/src/app/views/layouts/redux.rhtml
index 0918dce..fdb0691 100644
--- a/src/app/views/layouts/redux.rhtml
+++ b/src/app/views/layouts/redux.rhtml
@@ -16,6 +16,7 @@
   <%= stylesheet_link_tag 'flexigrid/flexigrid.css' %>
   <%= stylesheet_link_tag 'facebox' %>
   <%= stylesheet_link_tag 'jquery.jgrowl.css' %>
+  <%= stylesheet_link_tag 'ovirt-tree/tree' %>
 
   <%= javascript_include_tag "jquery-1.2.6.min.js" -%>
   <%= javascript_include_tag "jquery-treeview/jquery.treeview.js" -%>
@@ -33,6 +34,8 @@
 
   <%= javascript_include_tag "jquery.ui-1.5.2/ui/packed/ui.core.packed.js" -%>
   <%= javascript_include_tag "jquery.ui-1.5.2/ui/packed/ui.tabs.packed.js" -%>
+  <%= javascript_include_tag "trimpath-template-1.0.38.js" %>
+  <%= javascript_include_tag "ovirt.tree.js" %>
 
   <!-- ovirt-specific functions defined here -->
   <%= javascript_include_tag "ovirt.js" -%>
diff --git a/src/public/javascripts/ovirt.tree.js b/src/public/javascripts/ovirt.tree.js
index 1d8e26f..42719a1 100644
--- a/src/public/javascripts/ovirt.tree.js
+++ b/src/public/javascripts/ovirt.tree.js
@@ -82,4 +82,66 @@ function processChildren(list, templateObj){
       }
     }
   });
-}
\ No newline at end of file
+}
+
+(function($){
+	// widget prototype. Everything here is public
+	var Tree  = {
+                getTemplate: function () { return this.getData('template'); },
+		setTemplate: function (x) {
+                    this.setData('template', TrimPath.parseDOMTemplate(this.getData('template')));
+		},
+		init: function() {
+                    this.setTemplate(this.getTemplate());
+                    this.element.html(this.getTemplate().process(this.getData('content')));
+                    var self = this;
+                    this.element
+                    .find('li:has(ul)')
+                    .children('span.hitarea')
+                    .click(function(event){
+                      if (this == event.target) {
+                          if($(this).siblings('ul').size() >0) {
+                              if(self.getData('toggle') === 'toggle') {
+                                  self.toggle(event, this);  //we need 'this' so we have the right element to toggle
+                              } else {
+                                self.element.triggerHandler('toggle',[event,this],self.getData('toggle'));
+                              }
+                          }
+                      }
+                    });
+                    this.element
+                    .find('li > div')
+                    .filter(':not(.unclickable)')
+                    .bind('click', function(event) {
+                      if (this == event.target) {
+                          if(self.getData('clickHandler') === 'clickHandler') {
+                            self.clickHandler(event, this);  //we need 'this' so we have the right element to add click behavior to
+                          } else {
+                            self.element.triggerHandler('clickHandler',[event,this],self.getData('clickHandler'));
+                          }
+                      }
+                    });
+                },
+                toggle: function(e, elem) {
+                    $(elem)
+                      .toggleClass('expanded')
+                      .toggleClass('expandable')
+                      .siblings('ul').slideToggle("normal");
+                },
+                clickHandler: function(e,elem) {
+                    alert('e: ' + e + ', elem: ' + elem);
+                    var fred = 'fred';
+                },
+		off: function() {
+			this.element.css({background: 'none'});
+			this.destroy(); // use the predefined function
+		}
+	};
+	$.yi = $.yi || {}; // create the namespace
+	$.widget("yi.tree", Tree);
+	$.yi.tree.defaults = {
+            template: 'tree_template',
+            toggle: 'toggle',
+            clickHandler: 'clickHandler'
+	};
+})(jQuery);
\ No newline at end of file
diff --git a/src/public/stylesheets/ovirt-tree/tree.css b/src/public/stylesheets/ovirt-tree/tree.css
index 5fefb90..bc5cca5 100644
--- a/src/public/stylesheets/ovirt-tree/tree.css
+++ b/src/public/stylesheets/ovirt-tree/tree.css
@@ -21,7 +21,12 @@
     background-repeat: no-repeat;
     background-position: left;
     padding: 4px 0 4px 28px;
-    cursor: pointer;
+    cursor: pointer; /* maybe move this into a clickable class? */
+}
+
+.unclickable {
+    color: grey;
+    cursor: default !important;
 }
 
 .HardwarePool {
-- 
1.5.5.1




More information about the ovirt-devel mailing list