[issue #195] Added AJAX to /projects list.

This commit is contained in:
George Vinogradov 2012-03-27 19:50:00 +04:00
parent a3aaf4f7ce
commit 9bb1d80172
10 changed files with 176 additions and 5 deletions

View File

@ -19,6 +19,8 @@ gem 'russian', '~> 0.6.0'
gem 'highline', '~> 1.6.11'
gem 'rails-xmlrpc', '~> 0.3.6' # :git => 'git://github.com/chipiga/rails-xmlrpc.git'
gem 'jbuilder'
# gem 'rugged', '~> 0.16.0'
gem 'grack', :git => 'git://github.com/rdblue/grack.git', :require => 'git_http'
gem "grit", :git => 'git://github.com/chipiga/grit.git'

View File

@ -63,6 +63,7 @@ GEM
arel (3.0.2)
bcrypt-ruby (3.0.1)
bcrypt-ruby (3.0.1-java)
blankslate (2.1.2.4)
bluepill (0.0.60)
activesupport (>= 3.0.0)
daemons (~> 1.1.4, <= 1.1.6)
@ -141,6 +142,9 @@ GEM
hike (1.2.1)
hirb (0.6.2)
i18n (0.6.0)
jbuilder (0.4.0)
activesupport (>= 3.0.0)
blankslate (>= 2.1.2.4)
journey (1.0.3)
jquery-rails (2.0.1)
railties (>= 3.2.0, < 5.0)
@ -336,6 +340,7 @@ DEPENDENCIES
haml-rails (~> 0.3.4)
highline (~> 1.6.11)
hirb
jbuilder
jquery-rails (~> 2.0.1)
mailcatcher
meta-tags (~> 1.2.5)

View File

@ -636,6 +636,10 @@ ul.ui-autocomplete {
z-index: 999 !important;
}
table.dataTable {
margin: 10px 0 15px;
}
table.tablesorter tr.search th {
background: none repeat scroll 0 0 #DCECFA;
}

View File

@ -4,7 +4,13 @@ class ProjectsController < ApplicationController
load_and_authorize_resource
def index
@projects = Project.accessible_by(current_ability, :members).recent.paginate(:page => params[:page])
@projects = Project.accessible_by(current_ability, :members)
#puts prepare_list(@projects).inspect
respond_to do |format|
format.html { @projects = @projects.recent.paginate(:page => params[:page], :per_page => 25) }
format.json { @projects = prepare_list(@projects) }
end
# @projects = @projects.search(params[:query]).search_order if params[:query]
end
@ -78,6 +84,32 @@ class ProjectsController < ApplicationController
protected
def prepare_list(projects)
res = {}
colName = ['name']
sort_col = params[:iSortCol_0] || 0
sort_dir = params[:sSortDir_0] == "desc" ? 'desc' : 'asc'
order = "#{colName[sort_col.to_i]} #{sort_dir}"
res[:total_count] = projects.count
projects = projects.where(['projects.name ILIKE ?', "%#{ params[:sSearch] }%"]) if params[:sSearch] and !params[:sSearch].empty?
res[:filtered_count] = projects.count
projects = projects.order(order)
res[:projects] = if params[:iDisplayLength].present?
start = params[:iDisplayStart].present? ? params[:iDisplayStart].to_i : 0
length = params[:iDisplayLength].to_i
page = start/length + 1
projects.paginate(:page => page, :per_page => length)
else
projects
end
res
end
def choose_owner
if params[:who_owns] == 'group'
Group.find(params[:owner_id])

View File

@ -2,7 +2,13 @@
%td
= link_to project do
.table-sort-left= image_tag visibility_icon(project.visibility)
.table-sort-right #{project.owner.uname} / #{project.name}
.table-sort-right
= link_to project.owner.uname, project.owner.class == User ? user_path(project.owner) : group_path(project.owner) #{project.owner.uname} / #{project.name}
#{ ' / ' }
= link_to project.name, project_path(project)
%td.td2= project.description
%td= t("layout.collaborators.role_names.#{project.relations.by_user_through_groups(current_user).first.role}")
%td.td5= link_to image_tag('x.png'), remove_user_project_path(project), :method => :delete, :confirm => t("layout.confirm") unless project.owner == current_user
%td.td5
- unless project.owner == current_user
= link_to remove_user_project_path(project), :method => :delete, :confirm => t("layout.confirm") do
%span.delete &nbsp;

View File

@ -0,0 +1,17 @@
json.project do |proj|
proj.visibility project.visibility.to_s
proj.name project.name
proj.description project.description
proj.link project_path(project)
proj.role t("layout.collaborators.role_names.#{project.relations.by_user_through_groups(current_user).first.role}").force_encoding(Encoding::UTF_8)
proj.leave_link remove_user_project_path(project) unless project.owner == current_user
proj.owner do |owner|
owner.name project.owner.uname
owner.type project.owner.class.to_s.underscore
owner.link project.owner.class == User ? user_path(project.owner) : group_path(project.owner)
end
end

View File

@ -30,6 +30,46 @@
:javascript
$(document).ready(function() {
var JsonParser = function (json) {
var firstColumn = function(row) {
var project = row.project
var image = '<img alt="' + project.visibility + '" src="' + icons.visibilities[project.visibility] + '" />';
var owner = '<a href="' + project.owner.link + '">' + project.owner.name + '</a>';
var project = '<a href="' + project.link + '">' + project.name + '</a>';
return '<div class="table-sort-left">' + image + "</div>\n" +
'<div class="table-sort-right">' + owner + ' / ' + project + '<div>';
}
var lastColumn = function(row) {
var project = row.project
var res = '';
if (project.leave_link !== undefined) {
res = '<a href="' + project.leave_link + '" data-method="delete" rel="nofollow" data-confirm="' + messages.remove_confirm + '">' +
'<span class="delete">&nbsp;</span></a>';
}
return res;
}
var icons = json.icons;
var messages = json.messages;
var res = [];
for ( var i=0, iLen=json.aaData.length ; i<iLen ; i++ ) {
var data = json.aaData[i];
var inner = [];
inner.push( firstColumn(data) );
inner.push( data.project.description );
inner.push( data.project.role );
inner.push( lastColumn(data) );
res.push( inner );
}
return res;
}
var oTable = $('#datatable').dataTable({
"oLanguage": {
#{t("datatables.full")}
@ -39,9 +79,19 @@
"bLengthChange": false,
"aaSorting": [[ 0, 'asc' ]],
"sDom": 'rtip',
"bServerSide": true,
"sAjaxSource": "#{ projects_path :format => :json }",
"iDeferLoading": #{ @projects.count },
"aoColumns": [
#{ format_columns_for_datatable(columns) }
]
],
"fnServerData": function ( sSource, aoData, fnCallback ) {
$.getJSON( sSource, aoData, function (json) {
json.aaData = JsonParser(json);
fnCallback(json);
} );
}
});
$('#datatable_wrapper').append("<div class='both'></div>");
@ -63,7 +113,9 @@
return true;
});
$search.live('keyup', function() {
oTable.fnFilter(this.value);
if (this.value.length > 1) {
oTable.fnFilter(this.value);
}
});
});

View File

@ -0,0 +1,21 @@
json.sEcho h(params[:sEcho].to_i || -1)
json.iTotalRecords @projects[:total_count]
json.iTotalDisplayRecords @projects[:filtered_count]
json.messages do |msg|
msg.remove_confirm t("layout.confirm")
end
json.icons do |icons|
icons.visibilities do |vis|
Project::VISIBILITIES.each do |visibility|
vis.set!(visibility, image_path(visibility_icon(visibility)))
end
end
end
json.aaData do |aadata|
aadata.array!(@projects[:projects]) do |json, proj|
json.partial! 'project', :project => proj
end
end

View File

@ -0,0 +1,16 @@
en:
datatables:
full: |
"sProcessing": "Wait...",
"sZeroRecords": "No data accessible",
"sInfo": "Records displayed from _START_ to _END_ total _TOTAL_",
"sInfoEmpty": "Records displayed from 0 to 0 total 0",
"sInfoFiltered": "(filtered from _MAX_)",
"sInfoPostFix": "",
"sUrl": "",
"oPaginate": {
"sFirst": "« First",
"sPrevious": " Previous",
"sNext": "Next ",
"sLast": "Last »"
}

View File

@ -0,0 +1,16 @@
ru:
datatables:
full: |
"sProcessing": "Подождите...",
"sZeroRecords": "Нет доступных данных",
"sInfo": "Показаны записи с _START_ по _END_ из _TOTAL_",
"sInfoEmpty": "Показаны записи с 0 до 0 из 0",
"sInfoFiltered": "(отфильтровано из _MAX_)",
"sInfoPostFix": "",
"sUrl": "",
"oPaginate": {
"sFirst": "« Первая",
"sPrevious": " Предыдущая",
"sNext": "Следующая ",
"sLast": "Последняя »"
}