Jason Guiditta
2008-Oct-23 21:24 UTC
[Ovirt-devel] [PATCH server] Stage of one of tree conversions to pluggable widget.
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
Scott Seago
2008-Oct-27 18:50 UTC
[Ovirt-devel] [PATCH server] Stage of one of tree conversions to pluggable widget.
Jason Guiditta wrote:> 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(-) >ACK Works for me Scott