[Ovirt-devel] [PATCH] ok, now we have some ajax form validation.

Scott Seago sseago at redhat.com
Thu May 22 16:16:40 UTC 2008


I haven't gone crazy with validation rules -- mostly left things as they were, but added a few more validates_presence_of bits in the models.
create methods now return a json response with the field errors, if there are any. I haven't tested base-level error messages (i.e. general errors not connected to a form field) -- I'll probably need to make a couple more changes to support that. But basic field-level errors are being reported fine.

Also, for any of the action links/popups requiring grid checkboxes, I've added client-side validation to only perform the action if at least one box is checked -- displaying an error popup if there aren't any.

Signed-off-by: Scott Seago <sseago at redhat.com>
---
 wui/src/app/controllers/hardware_controller.rb  |   11 +++--
 wui/src/app/controllers/resources_controller.rb |    9 +++-
 wui/src/app/controllers/storage_controller.rb   |   26 ++++++------
 wui/src/app/controllers/vm_controller.rb        |   39 +++++++-----------
 wui/src/app/models/iscsi_storage_pool.rb        |    1 +
 wui/src/app/models/nfs_storage_pool.rb          |    1 +
 wui/src/app/models/pool.rb                      |    2 +
 wui/src/app/models/storage_pool.rb              |    2 +
 wui/src/app/models/vm.rb                        |    6 ++-
 wui/src/app/views/hardware/new.html.erb         |   15 ++++---
 wui/src/app/views/hardware/show_hosts.rhtml     |   24 ++++++++---
 wui/src/app/views/hardware/show_storage.rhtml   |   37 ++++++++++++-----
 wui/src/app/views/hardware/show_vms.rhtml       |   13 ++++--
 wui/src/app/views/host/addhost.html.erb         |   16 ++++---
 wui/src/app/views/layouts/redux.rhtml           |   49 ++++++++++++++++++-----
 wui/src/app/views/permission/new.rhtml          |    7 ++-
 wui/src/app/views/resources/new.rhtml           |    7 ++-
 wui/src/app/views/resources/show_vms.rhtml      |   13 ++++--
 wui/src/app/views/storage/addstorage.html.erb   |   15 ++++---
 wui/src/app/views/storage/new.rhtml             |    7 ++-
 wui/src/app/views/user/_show.rhtml              |   20 ++++++---
 wui/src/app/views/vm/_form.rhtml                |    4 +-
 wui/src/app/views/vm/new.rhtml                  |    7 ++-
 wui/src/public/stylesheets/layout.css           |    7 +++-
 24 files changed, 218 insertions(+), 120 deletions(-)

diff --git a/wui/src/app/controllers/hardware_controller.rb b/wui/src/app/controllers/hardware_controller.rb
index 25201d9..296fec3 100644
--- a/wui/src/app/controllers/hardware_controller.rb
+++ b/wui/src/app/controllers/hardware_controller.rb
@@ -281,12 +281,13 @@ class HardwareController < ApplicationController
     resource_ids_str = params[:resource_ids]
     resource_ids = []
     resource_ids = resource_ids_str.split(",").collect {|x| x.to_i} if resource_ids_str
-    @pool.create_with_resources(@parent, resource_type, resource_ids)
-    render :json => "created new Hardware Pool pool #{@pool.name}".to_json
+    begin
+      @pool.create_with_resources(@parent, resource_type, resource_ids)
+      render :json => { :object => "pool", :success => true, :alert => "Storage Pool was successfully created." }
+    rescue
+      render :json => { :object => "pool", :success => false, :errors => @pool.errors  }
+    end
 
-    
-    # FIXME: need to handle proper error messages w/ ajax (catch exception from save!)
-    #render :action => "new"
   end
 
   def edit
diff --git a/wui/src/app/controllers/resources_controller.rb b/wui/src/app/controllers/resources_controller.rb
index 2421e4b..ec0d6e7 100644
--- a/wui/src/app/controllers/resources_controller.rb
+++ b/wui/src/app/controllers/resources_controller.rb
@@ -98,10 +98,13 @@ class ResourcesController < ApplicationController
   end
 
   def create
-    @vm_resource_pool.create_with_parent(@parent)
-    render :json => "created new VM pool #{@vm_resource_pool.name}".to_json
+    begin
+      @vm_resource_pool.create_with_parent(@parent)
+      render :json => { :object => "vm_resource_pool", :success => true, :alert => "Storage Pool was successfully created." }
+    rescue
+      render :json => { :object => "vm_resource_pool", :success => false, :errors => @vm_resource_pool.errors  }
+    end
     
-    # FIXME: need to handle proper error messages w/ ajax (catch exception from save!)
   end
 
   def edit
diff --git a/wui/src/app/controllers/storage_controller.rb b/wui/src/app/controllers/storage_controller.rb
index 2f5c3f2..1378db8 100644
--- a/wui/src/app/controllers/storage_controller.rb
+++ b/wui/src/app/controllers/storage_controller.rb
@@ -96,31 +96,28 @@ class StorageController < ApplicationController
                               :storage_pool_id => @storage_pool.id,
                               :action          => StorageTask::ACTION_REFRESH_POOL,
                               :state           => Task::STATE_QUEUED})
-    @task.save
+    @task.save!
   end
 
   def refresh
-    if insert_refresh_task
+    begin
+      insert_refresh_task
       storage_url = url_for(:controller => "storage", :action => "show", :id => @storage_pool)
       flash[:notice] = 'Storage pool refresh was successfully scheduled.'
-    else
+    rescue
       flash[:notice] = 'Error scheduling Storage pool refresh.'
     end
     redirect_to :action => 'show', :id => @storage_pool.id
   end
 
   def create
-    if @storage_pool.save
-      if insert_refresh_task
-        render :json => "created new storage pool #{@storage_pool.display_name}".to_json
-      else
-        # FIXME: need to handle proper error messages w/ ajax
-        render :action => 'new'
-      end
-    else 
-      # FIXME: need to handle proper error messages w/ ajax
-      flash[:notice] = 'Storage Pool creation failed.'
-      redirect_to :controller => @storage_pool.hardware_pool.get_controller, :action => 'show', :id => @storage_pool.hardware_pool_id
+    begin
+      @storage_pool.save!
+      insert_refresh_task
+      render :json => { :object => "storage_pool", :success => true, :alert => "Storage Pool was successfully created." }
+    rescue
+      # FIXME: need to distinguish pool vs. task save errors (but should mostly be pool)
+      render :json => { :object => "storage_pool", :success => false, :errors => @storage_pool.errors  }
     end
   end
 
@@ -128,6 +125,7 @@ class StorageController < ApplicationController
   end
 
   def update
+    # FIXME: handle save! properly, in conjunction w/ update_attributes, json, etc
     if @storage_pool.update_attributes(params[:storage_pool])
       if insert_refresh_task
         storage_url = url_for(:controller => "storage", :action => "show", :id => @storage_pool)
diff --git a/wui/src/app/controllers/vm_controller.rb b/wui/src/app/controllers/vm_controller.rb
index 3cc98db..faf44de 100644
--- a/wui/src/app/controllers/vm_controller.rb
+++ b/wui/src/app/controllers/vm_controller.rb
@@ -39,40 +39,33 @@ class VmController < ApplicationController
   end
 
   def create
-    if @vm.save
+    begin
+      @vm.save!
       @task = VmTask.new({ :user    => @user,
                          :vm_id   => @vm.id,
                          :action  => VmTask::ACTION_CREATE_VM,
                          :state   => Task::STATE_QUEUED})
-      if @task.save
-        flash[:notice] = 'Vm was successfully created.'
-        start_now = params[:start_now]
-        if (start_now)
-          if @vm.get_action_list.include?(VmTask::ACTION_START_VM)
-            @task = VmTask.new({ :user    => @user,
+      @task.save!
+      start_now = params[:start_now]
+      if (start_now)
+        if @vm.get_action_list.include?(VmTask::ACTION_START_VM)
+          @task = VmTask.new({ :user    => @user,
                                :vm_id   => @vm.id,
                                :action  => VmTask::ACTION_START_VM,
                                :state   => Task::STATE_QUEUED})
-            if @task.save
-              render :json => 'Vm was successfully created. VM Start action queued.'.to_json
-              return
-            else
-              # FIXME: need to handle proper error messages w/ ajax
-              flash[:notice] = flash[:notice] + ' Error in inserting Start task.'
-            end
-          else
-            render :json => 'Vm was successfully created. VM Start action queued. Resources are not available to start VM now.'.to_json
-            return
-          end
+          @task.save!
+          render :json => { :object => "vm", :success => true, :alert => "VM was successfully created. VM Start action queued." }
+        else
+          render :json => { :object => "vm", :success => true, :alert => "VM was successfully created. Resources are not available to start VM now." }
         end
       else
-        # FIXME: task creation should be in a transaction here; if it fails, no VM created
-        flash[:notice] = 'Error in inserting task.'
+        render :json => { :object => "vm", :success => true, :alert => "VM was successfully created." }
       end
-      render :json => flash[:notice].to_json
-    else
-      render :action => 'new'
+    rescue
+      # FIXME: need to distinguish vm vs. task save errors (but should mostly be vm)
+      render :json => { :object => "vm", :success => false, :errors => @vm.errors  }
     end
+
   end
 
   def edit
diff --git a/wui/src/app/models/iscsi_storage_pool.rb b/wui/src/app/models/iscsi_storage_pool.rb
index 9cc104d..1280834 100644
--- a/wui/src/app/models/iscsi_storage_pool.rb
+++ b/wui/src/app/models/iscsi_storage_pool.rb
@@ -19,6 +19,7 @@
 
 class IscsiStoragePool < StoragePool
   
+  validates_presence_of :port, :target
   validates_uniqueness_of :ip_addr, :scope => [:port, :target]
   
   def label_components
diff --git a/wui/src/app/models/nfs_storage_pool.rb b/wui/src/app/models/nfs_storage_pool.rb
index 3704cc0..2d05305 100644
--- a/wui/src/app/models/nfs_storage_pool.rb
+++ b/wui/src/app/models/nfs_storage_pool.rb
@@ -19,6 +19,7 @@
 
 class NfsStoragePool < StoragePool
 
+  validates_presence_of :export_path
   validates_uniqueness_of :ip_addr, :scope => :export_path
 
   def label_components
diff --git a/wui/src/app/models/pool.rb b/wui/src/app/models/pool.rb
index cddd477..490c5e6 100644
--- a/wui/src/app/models/pool.rb
+++ b/wui/src/app/models/pool.rb
@@ -24,6 +24,8 @@ class Pool < ActiveRecord::Base
   # (needed for view code 'create' form)
   attr_accessor :tmp_parent
 
+  validates_presence_of :name
+
   # overloading this method such that we can use permissions.admins to get all the admins for an object
   has_many :permissions, :dependent => :destroy, :order => "id ASC" do
     def super_admins
diff --git a/wui/src/app/models/storage_pool.rb b/wui/src/app/models/storage_pool.rb
index 06c4b07..27479ee 100644
--- a/wui/src/app/models/storage_pool.rb
+++ b/wui/src/app/models/storage_pool.rb
@@ -26,6 +26,8 @@ class StoragePool < ActiveRecord::Base
     end
   end
 
+  validates_presence_of :ip_addr, :hardware_pool_id
+
   ISCSI = "iSCSI"
   NFS   = "NFS"
   STORAGE_TYPES = { ISCSI => "Iscsi",
diff --git a/wui/src/app/models/vm.rb b/wui/src/app/models/vm.rb
index d5866cc..a475e1d 100644
--- a/wui/src/app/models/vm.rb
+++ b/wui/src/app/models/vm.rb
@@ -25,7 +25,7 @@ class Vm < ActiveRecord::Base
   has_many :vm_tasks, :dependent => :destroy, :order => "id DESC"
   has_and_belongs_to_many :storage_volumes
   validates_presence_of :uuid, :description, :num_vcpus_allocated,
-                        :memory_allocated, :vnic_mac_addr
+                        :memory_allocated_in_mb, :memory_allocated, :vnic_mac_addr
 
   BOOT_DEV_HD          = "hd"
   BOOT_DEV_NETWORK     = "network"
@@ -173,6 +173,10 @@ class Vm < ActiveRecord::Base
   protected
   def validate
     resources = vm_resource_pool.max_resources_for_vm(self)
+    # FIXME: what should memory min/max be?
+    errors.add("memory_allocated_in_mb", "must be at least than 256 MB") unless memory_allocated_in_mb >=256
+    # FIXME: what should cpu min/max
+    errors.add("num_vcpus_allocated", "must be between 1 and 16") unless (num_vcpus_allocated >=1 and num_vcpus_allocated <= 16)
     errors.add("memory_allocated_in_mb", "violates quota") unless not(memory_allocated) or resources[:memory].nil? or memory_allocated <= resources[:memory]
     errors.add("num_vcpus_allocated", "violates quota") unless not(num_vcpus_allocated) or resources[:cpus].nil? or num_vcpus_allocated <= resources[:cpus]
     errors.add_to_base("No available nics in quota") unless resources[:nics].nil? or resources[:nics] >= 1
diff --git a/wui/src/app/views/hardware/new.html.erb b/wui/src/app/views/hardware/new.html.erb
index a67c837..22dfb86 100644
--- a/wui/src/app/views/hardware/new.html.erb
+++ b/wui/src/app/views/hardware/new.html.erb
@@ -5,7 +5,7 @@
   </div>
 </div>
 
-<form method="POST" action="<%= url_for :action => 'create' %>" id="new_hardware_pool_form" >
+<form method="POST" action="<%= url_for :action => 'create' %>" id="pool_form" >
 <div class="dialog_form">
   <%= render :partial => 'form' %>
 </div>
@@ -25,13 +25,16 @@ $(function() {
     };
 
     // bind form using 'ajaxForm' 
-    $('#new_hardware_pool_form').ajaxForm(hwpooloptions); 
+    $('#pool_form').ajaxForm(hwpooloptions); 
 });
 function afterNewHwPool(response, status){
-    jQuery(document).trigger('close.facebox');
-    // FIXME do we need to reload the tree here
-    <%= "$('##{@resource_type}_grid').flexReload()" if @resource_type %>
-    //$("#vmpools_grid").flexReload()
+    ajax_validation(response, status)
+    if (response.success) {
+      jQuery(document).trigger('close.facebox');
+      // FIXME do we need to reload the tree here
+      <%= "$('##{@resource_type}_grid').flexReload()" if @resource_type %>
+      //$("#vmpools_grid").flexReload()
+    }
 }
 </script>
 
diff --git a/wui/src/app/views/hardware/show_hosts.rhtml b/wui/src/app/views/hardware/show_hosts.rhtml
index 63a86ea..7f126a2 100644
--- a/wui/src/app/views/hardware/show_hosts.rhtml
+++ b/wui/src/app/views/hardware/show_hosts.rhtml
@@ -1,7 +1,10 @@
 <div id="toolbar_nav">
  <ul>
     <li><a href="<%= url_for :controller => 'host', :action => 'addhost', :hardware_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %>  Add Host</a></li>
-    <li><a href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'hosts' %>" rel="facebox[.bolder]"><%= image_tag "icon_move.png", :style=>"vertical-align:middle;" %>  Move</a></li>
+    <li>
+      <a id="move_link" href="#" onClick="return validate_for_move();"><%= image_tag "icon_move.png", :style=>"vertical-align:middle;" %>  Move</a>
+      <a id="move_link_hidden" href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'hosts' %>" rel="facebox[.bolder]" style="display:none" ></a>
+    </li>
     <li><a href="#" onClick="remove_hosts()"><%= image_tag "icon_delete_white.png" %>  Delete</a></li>
  </ul>
 </div>
@@ -11,13 +14,22 @@
   {
     return get_selected_checkboxes(document.hosts_grid_form)
   }
+  function validate_for_move()
+  {
+    if (validate_selected(get_selected_hosts(), 'host')) {
+      $('#move_link_hidden').click()
+    }
+  }
   function remove_hosts()
   {
-    $.post('<%= url_for :controller => "hardware", :action => "move_hosts", :id => @pool %>',
-           { resource_ids: get_selected_hosts().toString(), target_pool_id: <%= Pool.root.id %> },
-            function(data,status){
-              $("#hosts_grid").flexReload()
-             });
+    hosts = get_selected_hosts()
+    if (validate_selected(hosts, "host")) {
+      $.post('<%= url_for :controller => "hardware", :action => "move_hosts", :id => @pool %>',
+             { resource_ids: hosts.toString(), target_pool_id: <%= Pool.root.id %> },
+              function(data,status){
+                $("#hosts_grid").flexReload()
+               });
+    }
   }
   function hosts_select(selected_rows)
   {
diff --git a/wui/src/app/views/hardware/show_storage.rhtml b/wui/src/app/views/hardware/show_storage.rhtml
index 7ef69c9..f673e07 100644
--- a/wui/src/app/views/hardware/show_storage.rhtml
+++ b/wui/src/app/views/hardware/show_storage.rhtml
@@ -2,7 +2,10 @@
 <ul>
     <li><a href="<%= url_for :controller => 'storage', :action => 'addstorage', :hardware_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addstorage.png", :style => "vertical-align:middle;" %>  Add Storage Server</a></li>
     <li><a href="<%= url_for :controller => 'storage', :action => 'new', :hardware_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addstorage.png", :style => "vertical-align:middle;" %>  Create Storage Server</a></li>
-    <li><a href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'storage' %>" rel="facebox[.bolder]"><%= image_tag "icon_move.png", :style=>"vertical-align:middle;" %>  Move</a></li>
+    <li>
+      <a href="#" onClick="return validate_for_move();" ><%= image_tag "icon_move.png", :style=>"vertical-align:middle;" %>  Move</a>
+      <a id="move_link_hidden" href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'storage' %>" rel="facebox[.bolder]"  style="display:none" ></a>
+    </li>
     <li><a href="#" onClick="delete_storage()"><%= image_tag "icon_delete_white.png", :style => "vertical-align:middle;" %>  Delete</a></li>
     <li><a href="#" onClick="remove_storage()"><%= image_tag "icon_delete_white.png", :style => "vertical-align:middle;" %>  Remove</a></li>
   </ul>
@@ -13,21 +16,33 @@
   {
     return get_selected_checkboxes(document.storage_grid_form)
   }
+  function validate_for_move()
+  {
+    if (validate_selected(get_selected_storage(), 'storage pool')) {
+      $('#move_link_hidden').click()
+    }
+  }
   function remove_storage()
   {
-    $.post('<%= url_for :controller => "hardware", :action => "move_storage", :id => @pool %>',
-           { resource_ids: get_selected_storage().toString(), target_pool_id: <%= Pool.root.id %> },
-            function(data,status){
-              $("#storage_grid").flexReload()
-             });
+    storage = get_selected_storage()
+    if (validate_selected(storage, "storage pool")) {
+      $.post('<%= url_for :controller => "hardware", :action => "move_storage", :id => @pool %>',
+             { resource_ids: storage.toString(), target_pool_id: <%= Pool.root.id %> },
+              function(data,status){
+                $("#storage_grid").flexReload()
+               });
+    }
   }
   function delete_storage()
   {
-    $.post('<%= url_for :controller => "storage", :action => "delete_pools", :id => @pool %>',
-           { storage_pool_ids: get_selected_storage().toString() },
-            function(data,status){
-              $("#storage_grid").flexReload()
-             });
+    storage = get_selected_storage()
+    if (validate_selected(storage, "storage pool")) {
+      $.post('<%= url_for :controller => "storage", :action => "delete_pools", :id => @pool %>',
+             { storage_pool_ids: storage.toString() },
+              function(data,status){
+                $("#storage_grid").flexReload()
+               });
+    }
   }
   function storage_select(selected_rows)
   {
diff --git a/wui/src/app/views/hardware/show_vms.rhtml b/wui/src/app/views/hardware/show_vms.rhtml
index 86477be..44b6f50 100644
--- a/wui/src/app/views/hardware/show_vms.rhtml
+++ b/wui/src/app/views/hardware/show_vms.rhtml
@@ -11,11 +11,14 @@
   }
   function delete_vm_pools()
   {
-    $.post('<%= url_for :controller => "resources", :action => "delete", :id => @pool %>',
-           { vm_pool_ids: get_selected_vm_pools().toString() },
-            function(data,status){
-              $("#vmpools_grid").flexReload()
-             });
+    vm_pools = get_selected_vm_pools()
+    if (validate_selected(vm_pools, "vm_pool")) {
+      $.post('<%= url_for :controller => "resources", :action => "delete", :id => @pool %>',
+             { vm_pool_ids: vm_pools.toString() },
+              function(data,status){
+                $("#vmpools_grid").flexReload()
+               });
+    }
   }
   function vmpools_select(selected_rows)
   {
diff --git a/wui/src/app/views/host/addhost.html.erb b/wui/src/app/views/host/addhost.html.erb
index 18b8683..5c6844d 100644
--- a/wui/src/app/views/host/addhost.html.erb
+++ b/wui/src/app/views/host/addhost.html.erb
@@ -27,13 +27,15 @@
   {
     var assigned_selected= get_selected_checkboxes(document.addhosts_assigned_grid_form)
     var unassigned_selected= get_selected_checkboxes(document.addhosts_unassigned_grid_form)
-    
-    $.post('<%= url_for :controller => "hardware", :action => "add_hosts", :id => @hardware_pool %>',
-           { host_ids: Array.concat(assigned_selected,unassigned_selected).toString() },
-            function(data,status){ 
-              jQuery(document).trigger('close.facebox');
-              $("#hosts_grid").flexReload()
-             });
+    var hosts = Array.concat(assigned_selected,unassigned_selected)
+    if (validate_selected(hosts, "host")) {
+      $.post('<%= url_for :controller => "hardware", :action => "add_hosts", :id => @hardware_pool %>',
+             { host_ids: hosts.toString() },
+              function(data,status){ 
+                jQuery(document).trigger('close.facebox');
+                $("#hosts_grid").flexReload()
+               });
+    }
   }
 </script>
   <div class="panel_header"></div>
diff --git a/wui/src/app/views/layouts/redux.rhtml b/wui/src/app/views/layouts/redux.rhtml
index 3a0eb21..bb2bd09 100644
--- a/wui/src/app/views/layouts/redux.rhtml
+++ b/wui/src/app/views/layouts/redux.rhtml
@@ -27,7 +27,6 @@
   <%= javascript_include_tag "ui.slider.js" -%>
   <%= javascript_include_tag "jquery.cookie.js" -%>
   <%= javascript_include_tag "jquery.form.js" -%>
-  <%= yield :scripts -%>
     <script type="text/javascript">
       $(document).ready(function(){         
         $("#tree").treeview({
@@ -46,19 +45,49 @@
     var selected_array = new Array()
     var selected_index = 0
     var checkboxes
-    if (obj_form.grid_checkbox.length == undefined) {
-      checkboxes = [obj_form.grid_checkbox]
+    if (obj_form.grid_checkbox) {
+      if (obj_form.grid_checkbox.length == undefined) {
+        checkboxes = [obj_form.grid_checkbox]
+      } else {
+        checkboxes = obj_form.grid_checkbox
+      }
+      for(var i=0; i < checkboxes.length; i++){
+      if(checkboxes[i].checked)
+        {
+          selected_array[selected_index]= checkboxes[i].value
+          selected_index++
+        }
+      }
+    }
+    return selected_array
+  }
+  function validate_selected(selected_array, name)
+  {
+    if (selected_array.length == 0) {
+      alert("Please select at least one " + name + "  to continue")
+      return false
     } else {
-      checkboxes = obj_form.grid_checkbox
+      return true
     }
-    for(var i=0; i < checkboxes.length; i++){
-    if(checkboxes[i].checked)
-      {
-        selected_array[selected_index]= checkboxes[i].value
-        selected_index++
+  }
+  function ajax_validation(response, status)
+  {
+    if (response.object) {
+      $(".fieldWithErrors").removeClass("fieldWithErrors");
+      $("div.errorExplanation").remove();
+      if (!response.success) {
+        for(i=0; i<response.errors.length; i++) { 
+          var element = $("div.form_field:has(#"+response.object + "_" + response.errors[i][0]+")");
+          if (element) {
+            element.addClass("fieldWithErrors");
+            element.append('<div class="errorExplanation">'+response.errors[i][1]+'</div>');
+          }
+        }
+      }
+      if (response.alert) {
+        alert(response.alert)
       }
     }
-    return selected_array
   }
         
       </script>
diff --git a/wui/src/app/views/permission/new.rhtml b/wui/src/app/views/permission/new.rhtml
index f2b129f..2d95cde 100644
--- a/wui/src/app/views/permission/new.rhtml
+++ b/wui/src/app/views/permission/new.rhtml
@@ -25,8 +25,11 @@ $(function() {
     $('#new_permission_form').ajaxForm(permissionoptions); 
 });
 function afterNewPermission(response, status){
-    jQuery(document).trigger('close.facebox');
-    $("#users_grid").flexReload()
+    ajax_validation(response, status)
+    if (response.success) {
+      jQuery(document).trigger('close.facebox');
+      $("#users_grid").flexReload()
+    }
 }
 </script>
 
diff --git a/wui/src/app/views/resources/new.rhtml b/wui/src/app/views/resources/new.rhtml
index c142fe7..c19e1ab 100644
--- a/wui/src/app/views/resources/new.rhtml
+++ b/wui/src/app/views/resources/new.rhtml
@@ -25,8 +25,11 @@ $(function() {
     $('#new_vm_pool_form').ajaxForm(vmpooloptions); 
 });
 function afterNewVmPool(response, status){
-    jQuery(document).trigger('close.facebox');
-    $("#vmpools_grid").flexReload()
+    ajax_validation(response, status)
+    if (response.success) {
+      jQuery(document).trigger('close.facebox');
+      $("#vmpools_grid").flexReload()
+    }
 }
 </script>
 
diff --git a/wui/src/app/views/resources/show_vms.rhtml b/wui/src/app/views/resources/show_vms.rhtml
index 34eb973..8f1f4a3 100644
--- a/wui/src/app/views/resources/show_vms.rhtml
+++ b/wui/src/app/views/resources/show_vms.rhtml
@@ -25,11 +25,14 @@
   }
   function delete_vms()
   {
-    $.post('<%= url_for :controller => "vm", :action => "delete", :id => @pool %>',
-           { vm_ids: get_selected_vms().toString() },
-            function(data,status){
-              $("#vms_grid").flexReload()
-             });
+    vms = get_selected_vms()
+    if (validate_selected(vms, "vm")) {
+      $.post('<%= url_for :controller => "vm", :action => "delete", :id => @pool %>',
+             { vm_ids: vms.toString() },
+              function(data,status){
+                $("#vms_grid").flexReload()
+               });
+    }
   }
   function vms_select(selected_rows)
   {
diff --git a/wui/src/app/views/storage/addstorage.html.erb b/wui/src/app/views/storage/addstorage.html.erb
index bdfd0cb..67cd920 100644
--- a/wui/src/app/views/storage/addstorage.html.erb
+++ b/wui/src/app/views/storage/addstorage.html.erb
@@ -27,12 +27,15 @@
   {
     var assigned_selected= get_selected_checkboxes(document.addstorage_assigned_grid_form)
     var unassigned_selected= get_selected_checkboxes(document.addstorage_unassigned_grid_form)
-    $.post('<%= url_for :controller => "hardware", :action => "add_storage", :id => @hardware_pool %>',
-           { storage_pool_ids: Array.concat(assigned_selected,unassigned_selected).toString() },
-            function(data,status){ 
-              jQuery(document).trigger('close.facebox');
-              $("#storage_grid").flexReload()
-             });
+    var storage = Array.concat(assigned_selected,unassigned_selected)
+    if (validate_selected(storage, "storage pool")) {
+      $.post('<%= url_for :controller => "hardware", :action => "add_storage", :id => @hardware_pool %>',
+             { storage_pool_ids: storage.toString() },
+              function(data,status){ 
+                jQuery(document).trigger('close.facebox');
+                $("#storage_grid").flexReload()
+               });
+    }
   }
 </script>
   <div class="panel_header"></div>
diff --git a/wui/src/app/views/storage/new.rhtml b/wui/src/app/views/storage/new.rhtml
index 37c6535..8a94a33 100644
--- a/wui/src/app/views/storage/new.rhtml
+++ b/wui/src/app/views/storage/new.rhtml
@@ -46,7 +46,10 @@ $(function() {
     $('#new_storage_pool_form').ajaxForm(storageoptions); 
 });
 function afterNewStoragePool(response, status){
-    jQuery(document).trigger('close.facebox');
-    $("#storage_grid").flexReload()
+    ajax_validation(response, status)
+    if (response.success) {
+      jQuery(document).trigger('close.facebox');
+      $("#storage_grid").flexReload()
+    }
 }
   </script>
diff --git a/wui/src/app/views/user/_show.rhtml b/wui/src/app/views/user/_show.rhtml
index a811062..03ecec6 100644
--- a/wui/src/app/views/user/_show.rhtml
+++ b/wui/src/app/views/user/_show.rhtml
@@ -12,19 +12,25 @@
   }
   function delete_users()
   {
-    $.post('<%= url_for :controller => "permission", :action => "delete", :id => pool_id %>',
-           { permission_ids: get_selected_users().toString() },
+    permissions = get_selected_users()
+    if (validate_selected(permissions, "user")) {
+      $.post('<%= url_for :controller => "permission", :action => "delete", :id => pool_id %>',
+           { permission_ids: permissions.toString() },
             function(data,status){
               $("#users_grid").flexReload()
              });
+    }
   }
   function update_users(role)
   {
-    $.post('<%= url_for :controller => "permission", :action => "update_roles" %>',
-           { permission_ids: get_selected_users().toString(), user_role: role },
-            function(data,status){
-              $("#users_grid").flexReload()
-             });
+    permissions = get_selected_users()
+    if (validate_selected(permissions, "users)) {
+      $.post('<%= url_for :controller => "permission", :action => "update_roles" %>',
+             { permission_ids: permissions.toString(), user_role: role },
+              function(data,status){
+                $("#users_grid").flexReload()
+               });
+    }
   }
 </script>
 
diff --git a/wui/src/app/views/vm/_form.rhtml b/wui/src/app/views/vm/_form.rhtml
index 9d8682e..44bfdd3 100644
--- a/wui/src/app/views/vm/_form.rhtml
+++ b/wui/src/app/views/vm/_form.rhtml
@@ -17,8 +17,8 @@
     <div class="clear_row"></div>
     <div style="float:left;width:150px;" >
       <%= text_field_with_label "CPUs:", "vm", "num_vcpus_allocated",  {:style=>"width:100px;"}, {:style=>"padding-right: 50px;"} %>
-      <div class="field_title">max to create: <%=create_resources[:cpus]%> mb </div>
-      <div class="field_title">max to start: <%=start_resources[:cpus]%> mb </div>
+      <div class="field_title">max to create: <%=create_resources[:cpus]%> </div>
+      <div class="field_title">max to start: <%=start_resources[:cpus]%> </div>
     </div>
     <div style="float:left;">
       <%= text_field_with_label "Memory:", "vm", "memory_allocated_in_mb",  {:style=>"width:100px;"}, {:afterfield=>" mb"} %>
diff --git a/wui/src/app/views/vm/new.rhtml b/wui/src/app/views/vm/new.rhtml
index 5f9c673..c330ef3 100644
--- a/wui/src/app/views/vm/new.rhtml
+++ b/wui/src/app/views/vm/new.rhtml
@@ -37,8 +37,11 @@ $(function() {
     $('#new_vm_form').ajaxForm(vmoptions); 
 });
 function afterNewVm(response, status){
-    jQuery(document).trigger('close.facebox');
-    $("#vms_grid").flexReload()
+    ajax_validation(response, status)
+    if (response.success) {
+      jQuery(document).trigger('close.facebox');
+      $("#vms_grid").flexReload()
+    }
 }
 </script>
 
diff --git a/wui/src/public/stylesheets/layout.css b/wui/src/public/stylesheets/layout.css
index 784b1ad..1c317af 100644
--- a/wui/src/public/stylesheets/layout.css
+++ b/wui/src/public/stylesheets/layout.css
@@ -341,7 +341,7 @@ textarea:focus, input:focus {
 }
 
 .textfield_effect {
-	padding: 2px 0 0 2px;
+    padding: 2px 0 0 2px;
     border-width: 1px;
     border-style: solid;
     border-color: #999999;
@@ -369,6 +369,11 @@ textarea:focus, input:focus {
   height: 5px;
 }
 
+.fieldWithErrors {
+  background-color: #c00;
+}
+
+
 
 
 /* This file skins sliders */
-- 
1.5.4.1


--------------070101050409030300030506--




More information about the ovirt-devel mailing list