Commit cff95191 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Dashboard perfomance improved. Filter for projects page

parent 6d5c9698
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
GitLab is a free Project/Repository management application GitLab is a free Project/Repository management application
<img src="http://gitlabhq.com/front.png" width="900" height="471">
## Application details ## Application details
rails 3.1 rails 3.1
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
//= require branch-graph //= require branch-graph
//= require_tree . //= require_tree .
$(function(){ $(document).ready(function(){
$(".one_click_select").live("click", function(){ $(".one_click_select").live("click", function(){
$(this).select(); $(this).select();
}); });
...@@ -27,8 +27,50 @@ $(function(){ ...@@ -27,8 +27,50 @@ $(function(){
$(".account-box").mouseenter(showMenu); $(".account-box").mouseenter(showMenu);
$(".account-box").mouseleave(resetMenu); $(".account-box").mouseleave(resetMenu);
$("#projects-list .project").live('click', function(e){
if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
location.href = $(this).attr("url");
e.stopPropagation();
return false;
}
});
$("#issues-table .issue").live('click', function(e){
if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
location.href = $(this).attr("url");
e.stopPropagation();
return false;
}
});
$(document).keypress(function(e) {
if( $(e.target).is(":input") ) return;
switch(e.which) {
case 115: focusSearch();
e.preventDefault();
}
});
}); });
function focusSearch() {
$("#search").focus();
}
function taggifyForm(){
var tag_field = $('#tag_field').tagify();
tag_field.tagify('inputField').autocomplete({
source: '/tags.json'
});
$('form').submit( function() {
var tag_field = $('#tag_field')
tag_field.val( tag_field.tagify('serialize') );
return true;
});
}
function updatePage(data){ function updatePage(data){
$.ajax({type: "GET", url: location.href, data: data, dataType: "script"}); $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
} }
......
$(document).ready(function(){
$(".day-commits-table li.commit").live('click', function(e){
if(e.target.nodeName != "A") {
location.href = $(this).attr("url");
e.stopPropagation();
return false;
}
});
});
var CommitsList = { var CommitsList = {
ref:null,
limit:0,
offset:0,
ref:null, init:
limit:0, function(ref, limit) {
offset:0, $(".day-commits-table li.commit").live('click', function(e){
if(e.target.nodeName != "A") {
init: location.href = $(this).attr("url");
function(ref, limit) { e.stopPropagation();
this.ref=ref; return false;
this.limit=limit; }
this.offset=limit; });
this.initLoadMore();
$('.loading').show();
},
getOld:
function() {
$('.loading').show();
$.ajax({
type: "GET",
url: location.href,
data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref,
complete: function(){ $('.loading').hide()},
dataType: "script"});
},
append: this.ref=ref;
function(count, html) { this.limit=limit;
$("#commits_list").append(html); this.offset=limit;
if(count > 0) {
this.offset += count;
this.initLoadMore(); this.initLoadMore();
} $('.loading').show();
}, },
getOld:
function() {
$('.loading').show();
$.ajax({
type: "GET",
url: location.href,
data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref,
complete: function(){ $('.loading').hide()},
dataType: "script"});
},
initLoadMore: append:
function() { function(count, html) {
$(window).bind('scroll', function(){ $("#commits_list").append(html);
if($(window).scrollTop() == $(document).height() - $(window).height()){ if(count > 0) {
$(window).unbind('scroll'); this.offset += count;
CommitsList.getOld(); this.initLoadMore();
} }
}); },
}
initLoadMore:
function() {
$(window).bind('scroll', function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
$(window).unbind('scroll');
CommitsList.getOld();
}
});
}
} }
$(document).ready(function(){ var ProjectsList = {
$("#projects-list .project").live('click', function(e){ limit:0,
if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { offset:0,
location.href = $(this).attr("url");
e.stopPropagation();
return false;
}
});
$("#issues-table .issue").live('click', function(e){ init:
if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { function(limit) {
location.href = $(this).attr("url"); this.limit=limit;
e.stopPropagation(); this.offset=limit;
return false; this.initLoadMore();
}
});
$(document).keypress(function(e) { $('.project_search').keyup(function() {
if( $(e.target).is(":input") ) return; var terms = $(this).val();
switch(e.which) { if (terms.length >= 2 || terms.length == 0) {
case 115: focusSearch(); url = $('.project_search').parent().attr('action');
e.preventDefault(); $.ajax({
} type: "GET",
}); url: location.href,
data: { 'terms': terms, 'replace': true },
dataType: "script"
});
}
});
},
}); getOld:
function() {
$('.loading').show();
$.ajax({
type: "GET",
url: location.href,
data: "limit=" + this.limit + "&offset=" + this.offset,
complete: function(){ $('.loading').hide()},
dataType: "script"});
},
function focusSearch() { replace:
$("#search").focus(); function(count, html) {
} $(".tile").html(html);
if(count == ProjectsList.limit) {
this.offset = count;
this.initLoadMore();
} else {
this.offset = 0;
}
},
function taggifyForm(){ append:
var tag_field = $('#tag_field').tagify(); function(count, html) {
$(".tile").append(html);
if(count > 0) {
this.offset += count;
this.initLoadMore();
}
},
tag_field.tagify('inputField').autocomplete({ initLoadMore:
source: '/tags.json' function() {
}); $(window).bind('scroll', function(){
if($(window).scrollTop() == $(document).height() - $(window).height()){
$('form').submit( function() { $(window).unbind('scroll');
var tag_field = $('#tag_field') $('.loading').show();
tag_field.val( tag_field.tagify('serialize') ); ProjectsList.getOld();
return true; }
}); });
}
} }
...@@ -647,3 +647,9 @@ h4.middle-panel { ...@@ -647,3 +647,9 @@ h4.middle-panel {
border-radius:3px; border-radius:3px;
float:left; float:left;
} }
.project_search {
margin: 1.5em 0;
padding: 8px !important;
width: 300px;
}
...@@ -3,7 +3,7 @@ class DashboardController < ApplicationController ...@@ -3,7 +3,7 @@ class DashboardController < ApplicationController
def index def index
@projects = current_user.projects.all @projects = current_user.projects.all
@active_projects = @projects.select(&:last_activity_date).sort_by(&:last_activity_date).reverse @active_projects = @projects.select(&:last_activity_date_cached).sort_by(&:last_activity_date_cached).reverse
respond_to do |format| respond_to do |format|
format.html format.html
......
...@@ -11,9 +11,10 @@ class ProjectsController < ApplicationController ...@@ -11,9 +11,10 @@ class ProjectsController < ApplicationController
before_filter :require_non_empty_project, :only => [:blob, :tree, :graph] before_filter :require_non_empty_project, :only => [:blob, :tree, :graph]
def index def index
source = current_user.projects @limit, @offset = (params[:limit] || 16), (params[:offset] || 0)
source = source.tagged_with(params[:tag]) unless params[:tag].blank? @projects = current_user.projects
@projects = source.all @projects = @projects.where("name LIKE ?", "%#{params[:terms]}%") unless params[:terms].blank?
@projects = @projects.limit(@limit).offset(@offset)
end end
def new def new
......
...@@ -35,9 +35,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -35,9 +35,8 @@ class MergeRequest < ActiveRecord::Base
end end
def diffs def diffs
commit = project.commit(source_branch)
commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)}
diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue []
end end
def last_commit def last_commit
......
...@@ -52,6 +52,9 @@ class Project < ActiveRecord::Base ...@@ -52,6 +52,9 @@ class Project < ActiveRecord::Base
scope :public_only, where(:private_flag => false) scope :public_only, where(:private_flag => false)
def self.active
joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
end
def self.access_options def self.access_options
{ {
...@@ -195,6 +198,24 @@ class Project < ActiveRecord::Base ...@@ -195,6 +198,24 @@ class Project < ActiveRecord::Base
last_activity.try(:created_at) last_activity.try(:created_at)
end end
def last_activity_date_cached(expire = 1.hour)
activity_date_key = "project_#{id}_activity_date"
cached_activities = Rails.cache.read(activity_date_key)
if cached_activities
activity_date = if cached_activities == "Never"
nil
else
cached_activities
end
else
activity_date = last_activity_date
Rails.cache.write(activity_date_key, activity_date || "Never", :expires_in => expire)
end
activity_date
end
# Get project updates from cache # Get project updates from cache
# or calculate. # or calculate.
def cached_updates(limit, expire = 2.minutes) def cached_updates(limit, expire = 2.minutes)
...@@ -204,7 +225,7 @@ class Project < ActiveRecord::Base ...@@ -204,7 +225,7 @@ class Project < ActiveRecord::Base
activities = cached_activities activities = cached_activities
else else
activities = updates(limit) activities = updates(limit)
Rails.cache.write(activities_key, activities, :expires_in => 60.seconds) Rails.cache.write(activities_key, activities, :expires_in => expire)
end end
activities activities
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
%span.project-name= project.name %span.project-name= project.name
%span.time %span.time
%strong Last activity: %strong Last activity:
= project.last_activity_date ? time_ago_in_words(project.last_activity_date) + " ago" : "Never" = project.last_activity_date_cached ? time_ago_in_words(project.last_activity_date_cached) + " ago" : "Never"
...@@ -15,3 +15,5 @@ ...@@ -15,3 +15,5 @@
ago ago
.clear .clear
- if @commits.empty?
%p.cgray Nothing to merge
...@@ -20,3 +20,5 @@ ...@@ -20,3 +20,5 @@
%p %p
%center No preview for this file type %center No preview for this file type
- if @diffs.empty?
%p.cgray Nothing to merge
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
%input{ :value => project.url_to_repo, :class => ['git-url', 'one_click_select', 'text', 'project_list_url'], :readonly => 'readonly' } %input{ :value => project.url_to_repo, :class => ['git-url', 'one_click_select', 'text', 'project_list_url'], :readonly => 'readonly' }
%p.title.activity %p.title.activity
%span Last Activity: %span Last Activity:
- last_note = project.notes.last - if project.last_activity_date_cached
= last_note ? last_note.created_at.stamp("24 Aug, 2011") : "Never" = project.last_activity_date_cached.stamp("24 Aug, 2011")
- else
%p.small-tags= tag_list project Never
.buttons .buttons
%a.browse-code.button.yellow{:href => tree_project_ref_path(project, project.root_ref)} Browse code %a.browse-code.button.yellow{:href => tree_project_ref_path(project, project.root_ref)} Browse code
......
...@@ -7,13 +7,23 @@ ...@@ -7,13 +7,23 @@
%h2.icon %h2.icon
%span %span
Projects Projects
%center
= form_tag projects_path, :method => :get, :remote => true, :id => "projects_search_form" do
= search_field_tag :project_search, nil, { :placeholder => 'Filter projects by name', :class => 'project_search text' }
%div.clear %div.clear
- unless @projects.empty? - unless @projects.empty?
%div{:class => "tile", :style => view_mode_style("tile")} %div{:class => "tile"}
= render "tile" = render "tile"
%div{:class => "list", :style => view_mode_style("list")} .clear
= render "list" .loading{ :style => "display:none;"}
%center= image_tag "ajax-loader.gif"
- if @projects.count == @limit
:javascript
$(function(){
ProjectsList.init(16);
});
- else - else
%center.prepend-top %center.prepend-top
%h2 %h2
......
- if params[:replace]
:plain
ProjectsList.replace(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}");
- else
:plain
ProjectsList.append(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}");
#if defined?(Footnotes) && Rails.env.development? #if defined?(Footnotes) && Rails.env.development?
#Footnotes.run! # first of all #Footnotes.run! # first of all
# ... other init code
#end #end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment