I used a tree.js (http://www.silverstripe.com/downloads/tree/)
controller as my lists
where somewhat hierarchical so it cut down on the screen real-estate for
very large lists.
I put two trees on the page side by side, the left tree is what I
currently have and
what I can choose from on the right.
I added check boxes to the right hand tree nodes, so I select the ones I
want and then
click a button below that basically replaces the items on the left side
with the ones
selected on the right.
Example code explains it better I guess
This example sets up roles and rights for a standard RBAC.
Rights has_and_belongs_to_many :roles
Roles has_and_belongs_to_many :rights
I setup the data by creating hashes in the controller which are
available to the view…
roll everything up into a hierarchical tree structure
top level is hash of roles
next level is hash of permissions with controller as key and array
of actions as value
@role_tree= {}
roles= Role.find_all
roles.each do |r|
ph= {}
rights= r.rights
rights.each do |p|
ph[p.controller] ||= []
ph[p.controller] << p.action
end
@role_tree[r.name] = ph
end
# creates a tree of controllers with the actions for each
controller
# top level is hash of controllers
# next level is an array of actions
@rights_tree= {}
rights= Right.find_all
rights.each do |r|
name= r.controller
@rights_tree[name] ||= []
@rights_tree[name] << r.action
end
end
The view is simple… (edit.rhtml)
Role and Rights Editor
Roles |
Rights |
<%= render_role_tree(@role_tree) %> |
<%= start_form_tag :action => 'edit' %>
<%= render_rights_tree(@rights_tree) %>
The checked items above will replace the Rights of the following
Roles:
<% @role_tree.each_key do |role| %>
<%= check_box_tag "role", role %> <%= role %>
<% end %>
<%= submit_tag "Allocate to selected Roles" %>
<%= end_form_tag %>
|
This part goes in helpers, and creates the html for the two trees this
is specific for
the silverstripe tree control)…
module RoleHelper
def render_role_tree(tree)
ret = ‘’
ret += “
tree.each_key do |r|
ret += '<li><a href="#">' + r + '</a>' # list roles
h= tree[r] # get hash of controllers/[actions]
unless h.empty?
ret += '<ul>'
h.each_key do |c|
ret += '<li><a href="#">' + c + '</a>' # list
controllers
a= h[c]
unless a.empty?
ret += ‘
end
ret += '</ul>'
end
ret += '</li>'
end
ret += '</ul>'
end
ret += '</li>'
end
ret += '</ul>'
ret
end
def render_rights_tree(tree)
ret = ''
ret += "<ul class='tree'>"
tree.each_key do |r|
ret += "<li><a href=\"#\">#{r}</a>"# list controllers
aa= tree[r] # get array of actions
unless aa.empty?
ret += '<ul>'
ret += "<li><a href=\"#\"
onclick="checkAll(‘right[#{r}][]’); return
false;">Check All"
aa.each do |a|
ret += ‘
’ + “<input type="checkbox"
name="right[#{r}][]"
value="#{a}" />” + a + ‘’ # list actions
end
ret += ‘’
end
ret += ‘’
end
ret += ‘’
ret
end
end
the action handler in the controller for the post is a little more
complicated in my
case, but basically goes through all the selected checkboxes and sets
the relevant habtms.
def edit
if request.post?
#p params
unless params[‘role’].nil?
a_roles= params[‘role’]
a_rights= params[‘right’]
unless a_rights.nil?
a_roles.each { |ar|
role= Role.find_by_name(ar)
unless role.nil?
role.rights.clear
a_rights.each { |controller, aa|
aa.each { |action|
right=
Right.find_by_controller_and_action(controller, action)
unless right.nil?
role.rights << right
#puts “Allocating right
#{controller}/#{action}
to #{ar}”
else
puts “Right
#{controller}/#{action} not found”
end
}
}
else
puts “Role #{ar} not found”
end
}
flash[:notice]= ‘rights updated’
else
flash[:warning]= ‘no rights were selected’
end
else
flash[:warning]= ‘You need to select the role to
allocate to’
end
end
end
Hope that helps and is not too complex