From: Jan Provaznik <[email protected]>
Replaced Datatables plugin with simpler HTML table because some
issues when JS is off. Major issue with Datatables is that it doesn't
degrades gracefully when JS is off and server-side pagination.
Images and instances are now displayed by HTML table
(there is new helper 'paginated_table'), this table keeps
all common functions like sorting, paginating, searching and
code is cleaner. Works with JS on or off.
---
src/app/controllers/image_controller.rb | 55 +++-------------
src/app/controllers/instance_controller.rb | 92 +++++++++++++++------------
src/app/controllers/pool_controller.rb | 63 +++++--------------
src/app/helpers/application_helper.rb | 70 +++++++++++++++++++++
src/app/models/image.rb | 18 ------
src/app/models/instance.rb | 13 ----
src/app/views/image/_images.haml | 13 ++++
src/app/views/image/show.haml | 17 +++++
src/app/views/image/show.html.erb | 83 -------------------------
src/app/views/instance/_instances.haml | 17 +++++
src/app/views/instance/index.html.erb | 4 +-
src/app/views/instance/new.html.erb | 72 ++++++++--------------
src/app/views/instance/select_image.haml | 4 +
src/app/views/instance/show.html.erb | 29 +---------
src/app/views/layouts/aggregator.haml | 1 +
src/app/views/pool/list.haml | 3 +
src/app/views/pool/list.html.erb | 38 -----------
src/public/javascripts/application.js | 35 +++++++++++
src/public/stylesheets/dcloud.css | 79 ++++++++++++++++++++++++
19 files changed, 349 insertions(+), 357 deletions(-)
create mode 100644 src/app/views/image/_images.haml
create mode 100644 src/app/views/image/show.haml
delete mode 100644 src/app/views/image/show.html.erb
create mode 100644 src/app/views/instance/_instances.haml
create mode 100644 src/app/views/instance/select_image.haml
create mode 100644 src/app/views/pool/list.haml
delete mode 100644 src/app/views/pool/list.html.erb
diff --git a/src/app/controllers/image_controller.rb
b/src/app/controllers/image_controller.rb
index d7858b1..b75f692 100644
--- a/src/app/controllers/image_controller.rb
+++ b/src/app/controllers/image_controller.rb
@@ -26,57 +26,24 @@ class ImageController < ApplicationController
end
def show
- # FIXME: check on privilege IMAGE_VIEW which currently doesn't exist
- #require_privilege(Privilege::POOL_VIEW, @pool)
- end
-
- def images_paginate
- # FIXME: check on privilege IMAGE_VIEW which currently doesn't exist
- #require_privilege(Privilege::POOL_VIEW, @pool)
-
- # datatables sends pagination in format:
- # iDisplayStart - start index
- # iDisplayLength - num of recs
- # => we need to count page num
- page = params[:iDisplayStart].to_i / Image::per_page
-
- if params[:mode].to_s == 'simple'
- simple_mode = true
- cols = Image::COLUMNS_SIMPLE
- default_order_col = 1
- else
- cols = Image::COLUMNS
- simple_mode = false
- default_order_col = 2
+ if params[:create_instance]
+ redirect_to :controller => 'instance', :action => 'new',
'instance[image_id]' => (params[:ids] || []).first
end
- order_col_rec = cols[params[:iSortCol_0].to_i]
- order_col = cols[default_order_col] unless order_col_rec &&
order_col_rec[:opts][:searchable]
- order = order_col[:id] + " " + (params[:sSortDir_0] == 'desc' ? 'desc' :
'asc')
+ require_privilege(Privilege::IMAGE_VIEW)
- @images = Image.search_filter(params[:sSearch],
Image::SEARCHABLE_COLUMNS).paginate(
- :page => page + 1,
+ @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ @order = params[:order] || 'name'
+ @images = Image.search_filter(params[:search],
Image::SEARCHABLE_COLUMNS).paginate(
+ :page => params[:page] || 1,
+ :order => @order + ' ' + @order_dir,
:include => :instances,
- :order => order,
:conditions => {:provider_id => nil}
)
- expand_button_html = "<img src='/images/dir_closed.png'>"
-
- data = @images.map do |i|
- if simple_mode
- [i.id, i.name, i.architecture, i.instances.size]
- else
- [i.id, expand_button_html, i.name, i.architecture, i.instances.size,
"TODO: some description here?"]
- end
+ if request.xhr? and params[:partial]
+ render :partial => 'images'
+ return
end
-
- render :json => {
- :sEcho => params[:sEcho],
- :iTotalRecords => @images.total_entries,
- :iTotalDisplayRecords => @images.total_entries,
- :aaData => data
- }
end
-
end
diff --git a/src/app/controllers/instance_controller.rb
b/src/app/controllers/instance_controller.rb
index 039ed3a..293c877 100644
--- a/src/app/controllers/instance_controller.rb
+++ b/src/app/controllers/instance_controller.rb
@@ -23,58 +23,68 @@ require 'util/taskomatic'
class InstanceController < ApplicationController
before_filter :require_user
+ layout :layout
- def index
+ def layout
+ return "aggregator" unless request.xhr?
end
- def paginated
- # datatables sends pagination in format:
- # iDisplayStart - start index
- # iDisplayLength - num of recs
- # => we need to count page num
- page = params[:iDisplayStart].to_i / Instance::per_page
-
- order_col_rec = Instance::COLUMNS[params[:iSortCol_0].to_i]
- order_col = Instance::COLUMNS[2] unless order_col_rec &&
order_col_rec[:opts][:searchable]
- order = order_col[:id] + " " + (params[:sSortDir_0] == 'desc' ? 'desc' :
'asc')
-
- # FIXME only return those instances in pools which user has instance_view
- @instances = Instance.search_filter(params[:sSearch],
Instance::SEARCHABLE_COLUMNS).paginate(
- :page => page + 1,
- :order => order
+ def index
+ require_privilege(Privilege::INSTANCE_VIEW)
+
+ @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ @order = params[:order] || 'name'
+ @instances = Instance.search_filter(params[:search],
Instance::SEARCHABLE_COLUMNS).paginate(
+ :page => params[:page] || 1,
+ :order => @order + ' ' + @order_dir
)
- recs = @instances.map do |i|
- [
- i.id,
- i.get_action_list.map {|action| "<a href=\"#{url_for :controller =>
"instance", :action => "instance_action", :id => i.id, :instance_action =>
action}\">#{action}</a>"}.join(" | "),
- i.name,
- i.state,
- i.hardware_profile.name,
- i.image.name,
- i.cloud_account.nil? ? "" : i.cloud_account.provider.name,
- i.cloud_account.nil? ? "" : i.cloud_account.name
- ]
+ if request.xhr? and params[:partial]
+ render :partial => 'instances'
+ return
end
-
- render :json => {
- :sEcho => params[:sEcho],
- :iTotalRecords => @instances.total_entries,
- :iTotalDisplayRecords => @instances.total_entries,
- :aaData => recs
- }
end
- # Right now this is essentially a duplicate of PoolController#show,
- # but really it should be a single instance should we decide to have a page
- # for that. Redirect on create was all that brought you here anyway, so
- # should be unused for the moment.
- def show
- @instances = Instance.find(:all, :conditions => {:pool_id => params[:id]})
- @pool = Pool.find(params[:id])
- require_privilege(Privilege::INSTANCE_VIEW,@pool)
+ def select_image
+ if params[:select]
+ redirect_to :action => 'new', 'instance[image_id]' => (params[:ids] ||
[]).first
+ end
+
+ require_privilege(Privilege::IMAGE_VIEW)
+ @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ @order = params[:order] || 'name'
+ @images = Image.search_filter(params[:search],
Image::SEARCHABLE_COLUMNS).paginate(
+ :page => params[:page] || 1,
+ :order => @order + ' ' + @order_dir,
+ :conditions => {:provider_id => nil}
+ )
+
+ if request.xhr? and params[:partial]
+ render :partial => 'image/images'
+ return
+ end
end
+ ## Right now this is essentially a duplicate of PoolController#show,
+ # # but really it should be a single instance should we decide to have a
page
+ # # for that. Redirect on create was all that brought you here anyway, so
+ # # should be unused for the moment.
+ #def show
+ # require_privilege(Privilege::INSTANCE_VIEW,@pool)
+ # @pool = Pool.find(params[:id])
+ # @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ # @order = params[:order] || 'name'
+ # @instances = Instance.search_filter(params[:search],
Instance::SEARCHABLE_COLUMNS).paginate(
+ # :page => params[:page] || 1,
+ # :order => @order + ' ' + @order_dir,
+ # :conditions => {:pool_id => @pool.id}
+ # )
+ # if request.xhr? and params[:partial]
+ # render :partial => 'instances'
+ # return
+ # end
+ #end
+
def new
@instance = Instance.new(params[:instance])
require_privilege(Privilege::INSTANCE_MODIFY, @instance.pool) if
@instance.pool
diff --git a/src/app/controllers/pool_controller.rb
b/src/app/controllers/pool_controller.rb
index e687c0b..fdb903d 100644
--- a/src/app/controllers/pool_controller.rb
+++ b/src/app/controllers/pool_controller.rb
@@ -36,10 +36,23 @@ class PoolController < ApplicationController
#FIXME: clean this up, many error cases here
@pool = Pool.find(params[:id])
require_privilege(Privilege::INSTANCE_VIEW,@pool)
- # pass nil into Taskomatic as we're not working off a task here
- Taskomatic.new(nil,logger).pool_refresh(@pool)
- @pool.reload
- @instances = @pool.instances
+ ## pass nil into Taskomatic as we're not working off a task here
+ #Taskomatic.new(nil,logger).pool_refresh(@pool)
+ #[email protected]
+
+ @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ @order = params[:order] || 'name'
+
+ @instances = Instance.search_filter(params[:search],
Instance::SEARCHABLE_COLUMNS).paginate(
+ :page => params[:page] || 1,
+ :order => @order + ' ' + @order_dir,
+ :conditions => {:pool_id => @pool.id}
+ )
+
+ if request.xhr? and params[:partial]
+ render :partial => 'instance/instances'
+ return
+ end
end
def hardware_profiles
@@ -89,48 +102,6 @@ class PoolController < ApplicationController
def delete
end
- def instances_paginate
- @pool = Pool.find(params[:id])
- require_privilege(Privilege::POOL_VIEW, @pool)
-
- # datatables sends pagination in format:
- # iDisplayStart - start index
- # iDisplayLength - num of recs
- # => we need to count page num
- page = params[:iDisplayStart].to_i / Instance::per_page
-
- order_col_rec = Instance::COLUMNS[params[:iSortCol_0].to_i]
- order_col = Instance::COLUMNS[2] unless order_col_rec &&
order_col_rec[:opts][:searchable]
- order = order_col[:id] + " " + (params[:sSortDir_0] == 'desc' ? 'desc' :
'asc')
-
- @instances = Instance.search_filter(params[:sSearch],
Instance::SEARCHABLE_COLUMNS).paginate(
- :page => page + 1,
- :order => order,
- :conditions => {:pool_id => @pool.id}
- )
-
- recs = @instances.map do |i|
- [
- i.id,
- i.get_action_list.map {|action| "<a href=\"#{url_for :controller =>
"instance", :action => "instance_action", :id => i.id, :instance_action =>
action}\">#{action}</a>"}.join(" | "),
- i.name,
- i.state,
- i.hardware_profile.name,
- i.image.name,
- i.cloud_account.nil? ? "" : i.cloud_account.provider.name,
- i.cloud_account.nil? ? "" : i.cloud_account.name
- ]
- end
-
- render :json => {
- :sEcho => params[:sEcho],
- :iTotalRecords => @instances.total_entries,
- :iTotalDisplayRecords => @instances.total_entries,
- :aaData => recs
- }
- end
-
-
def accounts_for_pool
@pool = Pool.find(params[:pool_id])
require_privilege(Privilege::ACCOUNT_VIEW,@pool)
diff --git a/src/app/helpers/application_helper.rb
b/src/app/helpers/application_helper.rb
index 4565fb0..9109e0f 100644
--- a/src/app/helpers/application_helper.rb
+++ b/src/app/helpers/application_helper.rb
@@ -185,4 +185,74 @@ module ApplicationHelper
end
day_str + hours_to_seconds
end
+
+ def column_header(column, order, order_dir, check_all)
+ next_dir = order_dir.to_s == 'asc' ? 'desc' : 'asc'
+ if order and column[:id] == order
+ dir = order_dir.to_s == 'desc' ? 'desc' : 'asc'
+ cls = "ordercol #{dir}"
+ else
+ cls = nil
+ end
+
+ if column[:sortable]
+ label = link_to(
+ column[:header],
+ {:action => controller.action_name, :partial => true, :order =>
column[:id], :order_dir => next_dir, :search => params[:search]},
+ :class => cls)
+ elsif check_all.to_s == column[:id]
+ label = check_box_tag 'check_all'
+ else
+ label = column[:header]
+ end
+
+ content_tag 'th', label
+ end
+
+ def paginated_table(html_id, columns, data, opts = {})
+ search_url = url_for(:partial => true, :order => opts[:order], :order_dir
=> opts[:order_dir])
+ extend_table_js = "<script
type=\"text/javascript\">extend_table('#{html_id}');#{opts[:load_callback]};</script>"
+ extend_sfield_js = "<script
type=\"text/javascript\">extend_table_search_field('#{html_id}',
'#{search_url}')</script>"
+
+ rows = data.map do |rec|
+ if block_given?
+ capture_haml{yield rec}
+ else
+ content_tag 'tr', :class => cycle('even', 'odd') do
+ columns.map { |c| content_tag 'td', rec[c[:id]] }
+ end
+ end
+ end
+
+ header_cols = columns.map {|c| column_header(c, opts[:order],
opts[:order_dir], opts[:check_all])}
+
+ table = content_tag 'table' do
+ content_tag('thead', content_tag('tr', header_cols)) +
content_tag('tbody', rows)
+ end
+
+ search = content_tag 'div', :class => 'search_field' do
+ 'Search ' + text_field_tag('search', params[:search], :size => 10)
+ end
+
+ header = content_tag 'div', :class => 'header' do
+ search + content_tag('div', opts[:title], :class => 'title')
+ end
+
+ footer = content_tag 'div', :class => 'footer' do
+ will_paginate(data, :params => {:partial => true}).to_s +
+ page_entries_info(data).to_s
+ end
+
+ ajax_content = table + footer + extend_table_js
+
+ if params[:partial] and request.xhr?
+ ajax_content
+ else
+ content_tag 'div', :id => html_id, :class => "dtable #{opts[:class]}" do
+ header +
+ content_tag('div', ajax_content, :class => 'wrapper') +
+ extend_sfield_js
+ end
+ end
+ end
end
diff --git a/src/app/models/image.rb b/src/app/models/image.rb
index 9df4185..f3304cf 100644
--- a/src/app/models/image.rb
+++ b/src/app/models/image.rb
@@ -48,24 +48,6 @@ class Image < ActiveRecord::Base
validates_presence_of :architecture, :if => :provider
- # used to get sorting column in controller and in view to generate datatable
definition and
- # html table structure
- COLUMNS = [
- {:id => 'id', :header => '<input type="checkbox" id="image_id_all"
onclick="checkAll(event)">', :opts => {:checkbox_id => 'image_id', :searchable
=> false, :sortable => false, :width => '1px', :class => 'center'}},
- {:id => 'expand_button', :header => '', :opts => {:searchable => false,
:sortable => false, :width => '1px'}},
- {:id => 'name', :header => 'Name', :opts => {:width => "30%"}},
- {:id => 'architecture', :header => 'Architecture', :opts => {:width =>
"10%"}},
- {:id => 'instances', :header => 'Instances', :opts => {:sortable => false,
:width => "10%"}},
- {:id => 'details', :header => '', :opts => {:sortable => false, :visible
=> false, :searchable => false}},
- ]
-
- COLUMNS_SIMPLE = [
- {:id => 'id', :header => '', :opts => {:visible => false, :searchable =>
false, :sortable => false, :width => '1px', :class => 'center'}},
- {:id => 'name', :header => 'Name', :opts => {:width => "50%"}},
- {:id => 'architecture', :header => 'Architecture', :opts => {:width =>
"30%"}},
- {:id => 'instances', :header => 'Instances', :opts => {:sortable => false,
:width => "20%"}},
- ]
-
SEARCHABLE_COLUMNS = %w(name architecture)
def provider_image?
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index 6be4931..0212e24 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -59,19 +59,6 @@ class Instance < ActiveRecord::Base
STATES = [STATE_NEW, STATE_PENDING, STATE_RUNNING,
STATE_SHUTTING_DOWN, STATE_STOPPED, STATE_CREATE_FAILED]
- # used to get sorting column in controller and in view to generate datatable
definition and
- # html table structure
- COLUMNS = [
- {:id => 'id', :header => '<input type="checkbox" id="image_id_all"
onclick="checkAll(event)">', :opts => {:checkbox_id => 'image_id', :searchable
=> false, :sortable => false, :width => '1px', :class => 'center'}},
- {:id => 'actions', :header => 'Actions', :opts => {:width => "10%",
:sortable => false}},
- {:id => 'name', :header => 'Name', :opts => {:width => "25%"}},
- {:id => 'state', :header => 'State', :opts => {:width => "10%"}},
- {:id => 'hwprofile', :header => 'HW profile', :opts => {:width => "15%"}},
- {:id => 'template', :header => 'Template', :opts => {:sortable => false,
:width => "15%"}},
- {:id => 'provider', :header => 'Provider', :opts => {:width => "10%"}},
- {:id => 'account', :header => 'Account', :opts => {:width => "10%"}},
- ]
-
SEARCHABLE_COLUMNS = %w(name state)
validates_inclusion_of :state,
diff --git a/src/app/views/image/_images.haml b/src/app/views/image/_images.haml
new file mode 100644
index 0000000..0ef78d9
--- /dev/null
+++ b/src/app/views/image/_images.haml
@@ -0,0 +1,13 @@
+- columns = [ |
+ {:id => 'id', :header => ''}, |
+ {:id => 'name', :header => 'Name', :sortable => true}, |
+ {:id => 'architecture', :header => 'Architecture', :sortable => true}, |
+ {:id => 'instances', :header => 'Instances'}, |
+] |
+
+= paginated_table('images_table', columns, @images, {:load_callback =>
'table_loaded()', :order => @order, :order_dir => @order_dir, :title => 'List
of templates', :check_all => 'id'}) do |rec|
+ %tr{:class => "#{cycle('even', 'odd')}"}
+ %td= check_box_tag 'ids[]', rec[:id]
+ %td{:class => 'image_name'}= rec[:name]
+ %td= rec[:architecture]
+ %td= rec[:instances]
diff --git a/src/app/views/image/show.haml b/src/app/views/image/show.haml
new file mode 100644
index 0000000..5720443
--- /dev/null
+++ b/src/app/views/image/show.haml
@@ -0,0 +1,17 @@
+- content_for :scripts do
+ :javascript
+ function check_checkboxes() {
+ var checked_count = $('input[name="ids[]"]:checked',
$("#images_table")).length;
+ $('input[name="create_instance"]').attr('disabled', checked_count != 1);
+ }
+ function table_loaded() {
+ //$("input[name='ids[]']", $("#images_table")).change(function()
{console.warn('x');check_checkboxes()});
+ //FIXME: this doesn't work in 100%, but don't know better way
+ $("#images_table").click(function() {check_checkboxes()});
+ check_checkboxes();
+ }
+
+- form_tag({:action => 'show'}, {:class => 'dtable_form'}) do
+ .action_buttons
+ = submit_tag "Create instance", :name => "create_instance"
+ = render :partial => 'images'
diff --git a/src/app/views/image/show.html.erb
b/src/app/views/image/show.html.erb
deleted file mode 100644
index 5a7cb53..0000000
--- a/src/app/views/image/show.html.erb
+++ /dev/null
@@ -1,83 +0,0 @@
-<script type="text/javascript">
-
- function fnOpenClose() {
- $('td img', dataTable_images_table.fnGetNodes() ).each( function () {
- $(this).click( function () {
- var nTr = this.parentNode.parentNode;
- if ( this.src.match('dir_open') )
- {
- /* This row is already open - close it */
- this.src = "/images/dir_closed.png";
- /* fnClose doesn't do anything for server-side processing - do it
ourselves :-) */
- var nRemove = $(nTr).next()[0];
- nRemove.parentNode.removeChild( nRemove );
- }
- else
- {
- /* Open this row */
- this.src = "/images/dir_open.png";
- dataTable_images_table.fnOpen( nTr,
dataTable_images_table.fnGetData(nTr)[5], 'details' );
- }
- });
- });
- }
-
- function getCheckedRows() {
- return $('input[name="image_id[]"]:checked',
dataTable_images_table).length;
- }
-
- function showButtons() {
- getCheckedRows();
- $('input[name="create_image"]').attr('disabled', getCheckedRows() != 1);
- }
-
- function checkRow(ev) {
- var box = $('input[name="image_id[]"]', ev.target.parentNode);
- if ($(ev.target).attr('name') != "image_id[]")
- box.attr('checked', !box.attr('checked'));
- showButtons();
- }
-
- function checkAll(ev) {
- $('input[name="image_id[]"]', dataTable_images_table).attr('checked',
$(ev.target).attr('checked'))
- }
-
- function drawCallback() {
- $('#image_id_all').attr('checked', false);
- fnOpenClose();
- }
-
- function createInstance() {
- var selected_row = $('input[name="image_id[]"]:checked',
dataTable_images_table);
- location.href = '<%= url_for(:controller => "instance", :action => "new")
%>?instance[image_id]=' + selected_row.attr('value');
- }
-</script>
-
-<%= datatable(
- Image::COLUMNS.map {|c| c[:opts]},
- {
- :table_dom_id => 'images_table',
- :per_page => Image::per_page,
- :sort_by => "[2, 'asc']",
- :serverside => true,
- :ajax_source => url_for(:controller => 'image', :action =>
'images_paginate'),
- :append => ".fnSetFilteringDelay()",
- :persist_state => false,
- :click_callback => "function(ev) {checkRow(ev);}",
- :draw_callback => "drawCallback",
- }
-) %>
- <div style="padding:20px">
- <input type="button" value="Create instance" name="create_image"
disabled=true onclick="createInstance()">
- </div>
- <table class="datatable display" id="images_table">
- <thead>
- <tr>
- <% Image::COLUMNS.each do |c| %>
- <%= "<th>#{c[:header]}</th>" %>
- <% end %>
- </tr>
- </thead>
- <tbody>
- </tbody>
-</table>
diff --git a/src/app/views/instance/_instances.haml
b/src/app/views/instance/_instances.haml
new file mode 100644
index 0000000..cc5a2c2
--- /dev/null
+++ b/src/app/views/instance/_instances.haml
@@ -0,0 +1,17 @@
+- columns = [ |
+ {:id => 'id', :header => ''}, |
+ {:id => 'name', :header => 'Name', :sortable => true}, |
+ {:header => 'Details'}, |
+ {:id => 'template', :header => 'Template'}, |
+ {:id => 'state', :sortable => true, :header => 'State'}, |
+ {:id => 'time_last_running', :header => 'Time last running'}, |
+] |
+
+= paginated_table('instances_table', columns, @instances, {:order => @order,
:order_dir => @order_dir, :title => 'List of instances', :check_all => 'id'})
do |rec|
+ %tr{:class => "#{cycle('even', 'odd')}"}
+ %td= check_box_tag 'ids[]', rec.id
+ %td= rec.name
+ %td Details
+ %td= rec.image.name
+ %td= rec.state
+ %td= rec.time_last_running
diff --git a/src/app/views/instance/index.html.erb
b/src/app/views/instance/index.html.erb
index c19c3fa..e57f78c 100644
--- a/src/app/views/instance/index.html.erb
+++ b/src/app/views/instance/index.html.erb
@@ -1 +1,3 @@
-<%= render :partial => 'list' %>
+<% form_tag({:action => 'instance_action'}, {:class => 'dtable_form'}) do %>
+ <%= render :partial => 'instance/instances' %>
+<% end %>
diff --git a/src/app/views/instance/new.html.erb
b/src/app/views/instance/new.html.erb
index 86810bc..fa46ac4 100644
--- a/src/app/views/instance/new.html.erb
+++ b/src/app/views/instance/new.html.erb
@@ -1,23 +1,32 @@
<script type="text/javascript">
- function showImages(ev) {
- $("#images_table_wrapper").css('display', 'block');
- images_dialog = $("#images_table_wrapper").dialog({
- title: "Select template for new instance",
- dialogClass: 'flora',
- width: 600,
- height: 500,
- modal: true,
- overlay: {opacity: 0.2, background: "black"}
+ $(document).ready(function() {
+ $(".select_image").click(function() {
+ var wrapper = $("#select_template_dialog");
+ if (wrapper.length == 0) wrapper = $('<div
id="select_template_dialog"></div>');
+ wrapper.dialog({
+ title: "Select template for new instance",
+ width: 600,
+ height: 500,
+ modal: true,
+ overlay: {opacity: 0.2, background: "black"}
+ });
+ wrapper.load('<%= url_for :action => 'select_image' %>', null,
extend_select_button);
+ return false;
});
- }
+ });
- function selectImage(ev) {
- var image_id = dataTable_images_table.fnGetData(ev.target.parentNode)[0];
- var image_name = dataTable_images_table.fnGetData(ev.target.parentNode)[1];
- $("#images_table_wrapper").css('display', 'none');
- $("#images_table_wrapper").dialog('close');
- $('input[name="image_selector"]').attr('value', image_name);
- $('input[name="instance[image_id]"]').attr('value', image_id);
+ function extend_select_button() {
+ $(":submit[name=select]").click(function() {
+ var checkbox = $("input[name='ids[]']:checked").first();
+ var id = checkbox.val();
+ if (id !== undefined) {
+ var name = $(".image_name", checkbox.parent().parent()).text();
+ $(".select_image").text(name);
+ $("input[name='instance[image_id]']").val(id);
+ }
+ $("#select_template_dialog").dialog('close');
+ return false;
+ });
}
function poolSelected(field) {
@@ -35,7 +44,7 @@
<li><label>Name<span>Name for this new Instance</span></label><%=
text_field :instance, :name, :class => "txtfield" %></li>
<li><label>Template<span>Choose a template to use</span></label>
- <input type="button" style="cursor:pointer" onclick="showImages(event)"
name="image_selector" value="<%= @instance.image ? @instance.image.name :
"click to select template"%>"/>
+ <%= link_to(@instance.image ? @instance.image.name : "Select template...",
{:action => 'select_image'}, {:class => 'actionlink select_image'}) %>
</li>
<input type=hidden name="instance[image_id]" value="<%= @instance.image ?
@instance.image.id : '' %>">
@@ -71,30 +80,3 @@
<%= submit_tag "Save", :class => "submit" %>
<% end %>
</div>
-
-<%= datatable(
- Image::COLUMNS_SIMPLE.map {|c| c[:opts]},
- {
- :table_dom_id => 'images_table',
- :per_page => Image::per_page,
- :sort_by => "[2, 'asc']",
- :serverside => true,
- :ajax_source => url_for(:controller => 'image', :action =>
'images_paginate') + "?mode=simple",
- :append => ".fnSetFilteringDelay()",
- :click_callback => "function(event) {selectImage(event)}",
- }
-) %>
-
-<div style="display:none" id="images_table_wrapper">
- <table class="datatable display" id="images_table">
- <thead>
- <tr>
- <% Image::COLUMNS_SIMPLE.each do |c| %>
- <%= "<th>#{c[:header]}</th>" %>
- <% end %>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
-</div>
diff --git a/src/app/views/instance/select_image.haml
b/src/app/views/instance/select_image.haml
new file mode 100644
index 0000000..c58d459
--- /dev/null
+++ b/src/app/views/instance/select_image.haml
@@ -0,0 +1,4 @@
+- form_tag({:action => 'select_image'}, {:class => 'dtable_form'}) do
+ = render :partial => 'image/images'
+ .action_buttons
+ = submit_tag "Select", :name => "select"
diff --git a/src/app/views/instance/show.html.erb
b/src/app/views/instance/show.html.erb
index a2bfe2f..689ead1 100644
--- a/src/app/views/instance/show.html.erb
+++ b/src/app/views/instance/show.html.erb
@@ -1,29 +1,2 @@
-<% if @instances.size == 0 %>
-<h1>There are no pools to display</h1>
-<% else %>
- <table>
- <thead>
- <tr>
- <th scope="col">Actions</th>
- <th scope="col">Name</th>
- </tr>
- </thead>
- <tbody>
- <%[email protected] {|instance| %>
- <tr>
- <td>
- <%instance.get_action_list.each {|action|%>
- <%= link_to action, :controller => "instance",
- :action => "instance_action",
- :id => instance,
- :instance_action => action %>
- <br/>
- <% } %>
- </td>
- <td><div><%= instance.name %></div></td>
- </tr>
- <% } %>
- </tbody>
- </table>
-<% end %>
+<%= render :partial => 'instance/instances' %>
<%= link_to "Add a new instance", :controller => "instance", :action => "new",
:id => @pool %>
diff --git a/src/app/views/layouts/aggregator.haml
b/src/app/views/layouts/aggregator.haml
index 0a187bb..c79dce7 100644
--- a/src/app/views/layouts/aggregator.haml
+++ b/src/app/views/layouts/aggregator.haml
@@ -14,6 +14,7 @@
= stylesheet_link_tag 'jquery.ui-1.8.1/jquery-ui-1.8.1.custom.css'
= stylesheet_link_tag 'jquery-datatables/demo_table_jui.css'
+ = javascript_include_tag "application.js"
= javascript_include_tag "jquery-1.4.2.min.js"
= javascript_include_tag "facebox.js"
= javascript_include_tag "jquery.ui-1.8.1/jquery-ui-1.8.1.custom.min.js"
diff --git a/src/app/views/pool/list.haml b/src/app/views/pool/list.haml
new file mode 100644
index 0000000..2014ed9
--- /dev/null
+++ b/src/app/views/pool/list.haml
@@ -0,0 +1,3 @@
+= render :partial => "instance/instances"
+
+= link_to "Add a new instance", {:controller => "instance", :action => "new",
"instance[pool_id]" => @pool}, :class=>"actionlink"
diff --git a/src/app/views/pool/list.html.erb b/src/app/views/pool/list.html.erb
deleted file mode 100644
index 38e46e7..0000000
--- a/src/app/views/pool/list.html.erb
+++ /dev/null
@@ -1,38 +0,0 @@
-<script type="text/javascript">
- function clickRow(ev) {
- var box = $('input[name="image_id[]"]', ev.target.parentNode);
- if ($(ev.target).attr('name') != "image_id[]")
- box.attr('checked', !box.attr('checked'));
- }
-
- function checkAll(ev) {
- $('input[name="image_id[]"]', dataTable_instances_table).attr('checked',
$(ev.target).attr('checked'))
- }
-</script>
-
-<%= datatable(
- Instance::COLUMNS.map {|c| c[:opts]},
- {
- :table_dom_id => 'instances_table',
- :per_page => Instance::per_page,
- :sort_by => "[3, 'asc']",
- :serverside => true,
- :ajax_source => url_for(:controller => 'pool', :action =>
'instances_paginate') + "/#[email protected]}",
- :append => ".fnSetFilteringDelay()",
- :persist_state => false,
- :click_callback => "function(ev) {clickRow(ev);}",
- }
-) %>
-
-<table class="datatable display" id="instances_table">
- <thead>
- <tr>
- <% Instance::COLUMNS.each do |c| %>
- <%= "<th>#{c[:header]}</th>" %>
- <% end %>
- </tr>
- </thead>
- <tbody>
- </tbody>
-</table>
-<%= link_to "Add a new instance", {:controller => "instance", :action =>
"new", "instance[pool_id]" => @pool}, :class=>"actionlink"%>
diff --git a/src/public/javascripts/application.js
b/src/public/javascripts/application.js
index fe45776..be1bc91 100644
--- a/src/public/javascripts/application.js
+++ b/src/public/javascripts/application.js
@@ -1,2 +1,37 @@
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
+
+function extend_table(id, search_url) {
+ var table = $("#" + id);
+ var wrapper = $(".wrapper", table);
+ // make column head links ajax
+ $("table thead tr th a", table).click(function()
{wrapper.load($(this).attr('href'));return false;});
+
+ // pagination links should by ajax too
+ $(".pagination a", table).click(function()
{wrapper.load($(this).attr('href'));return false;});
+
+ // check all checkboxes when checking "check all"
+ $("input[name='check_all']", table).click(function()
{$("input[name='ids[]']", table).attr('checked', $(this).attr('checked'))});
+
+ // check checkbox if row is clicked
+ $("table tbody tr", table).click(function(ev) {
+ if ($(ev.target).attr('name') == 'ids[]') return;
+ var box = $("input[name='ids[]']", this);
+ box.attr('checked', !box.attr('checked'));
+ });
+}
+
+// table ajax search with 1 sec delay
+function extend_table_search_field(id, search_url) {
+ var table = $("#" + id);
+ var wrapper = $(".wrapper", table);
+ $(".search_field input", table).keypress(function() {
+ if (table.search_lock) return;
+ table.search_lock = true;
+ setTimeout(function() {
+ table.search_lock = false;
+ var search = $(".search_field input", table).val();
+ wrapper.load(search_url + '&search=' + search);
+ }, 1000)
+ });
+}
diff --git a/src/public/stylesheets/dcloud.css
b/src/public/stylesheets/dcloud.css
index 0183a55..ec0ea63 100644
--- a/src/public/stylesheets/dcloud.css
+++ b/src/public/stylesheets/dcloud.css
@@ -301,3 +301,82 @@ a.button_link {
#dashboard-tabs ul, #provider-tabs ul, #pool-tabs ul{
float: none;
}
+
+/* paginated data table */
+.dtable {
+ border: 1px solid #bbb;
+}
+
+.dtable table {
+ width: 100%;
+}
+
+.dtable_form {
+ width: 96%;
+ padding: 20px 2% 20px 2%;
+}
+
+.dtable tr:hover {
+ background-color: #eee;
+}
+
+.dtable table th {
+ text-align: left;
+}
+
+.dtable .ordercol {
+ background-position:left center;
+ background-repeat:no-repeat;
+ padding-left:20px;
+}
+
+.dtable .asc {
+ background-image: url(../images/Sort_down_11.png);
+}
+
+.dtable .desc {
+ background-image: url(../images/Sort_up_11.png);
+}
+
+.dtable .header {
+ height: 25px;
+ background-color: #eee;
+ border-bottom: 1px solid #bbb;
+}
+
+.dtable .footer {
+ height: 24px;
+ background-color: #eee;
+ border-top: 1px solid #bbb;
+ line-height: 1.8;
+ padding-left: 10px;
+}
+
+.dtable .search_field {
+ font-size: 15px;
+ float: right;
+}
+
+.dtable .search_field input {
+ font-size: 15px;
+}
+
+.dtable .pagination {
+ float: right;
+ padding-right: 10px;
+}
+
+.dtable .pagination a {
+ color: blue;
+}
+
+.dtable .title {
+ font-size: 15px;
+ font-weight: bold;
+ padding-left: 10px;
+}
+
+.action_buttons {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
--
1.7.0.1
_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel