Dashboard perfomance improved. Filter for projects page
This commit is contained in:
parent
6d5c969872
commit
cff9519127
16 changed files with 215 additions and 112 deletions
|
@ -3,9 +3,6 @@
|
|||
GitLab is a free Project/Repository management application
|
||||
|
||||
|
||||
<img src="http://gitlabhq.com/front.png" width="900" height="471">
|
||||
|
||||
|
||||
## Application details
|
||||
|
||||
rails 3.1
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//= require branch-graph
|
||||
//= require_tree .
|
||||
|
||||
$(function(){
|
||||
$(document).ready(function(){
|
||||
$(".one_click_select").live("click", function(){
|
||||
$(this).select();
|
||||
});
|
||||
|
@ -27,8 +27,50 @@ $(function(){
|
|||
$(".account-box").mouseenter(showMenu);
|
||||
$(".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){
|
||||
$.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
|
||||
}
|
||||
|
|
|
@ -1,55 +1,52 @@
|
|||
$(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 = {
|
||||
ref:null,
|
||||
limit:0,
|
||||
offset:0,
|
||||
|
||||
ref:null,
|
||||
limit:0,
|
||||
offset:0,
|
||||
init:
|
||||
function(ref, limit) {
|
||||
$(".day-commits-table li.commit").live('click', function(e){
|
||||
if(e.target.nodeName != "A") {
|
||||
location.href = $(this).attr("url");
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
init:
|
||||
function(ref, limit) {
|
||||
this.ref=ref;
|
||||
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:
|
||||
function(count, html) {
|
||||
$("#commits_list").append(html);
|
||||
if(count > 0) {
|
||||
this.offset += count;
|
||||
this.ref=ref;
|
||||
this.limit=limit;
|
||||
this.offset=limit;
|
||||
this.initLoadMore();
|
||||
}
|
||||
},
|
||||
$('.loading').show();
|
||||
},
|
||||
|
||||
initLoadMore:
|
||||
function() {
|
||||
$(window).bind('scroll', function(){
|
||||
if($(window).scrollTop() == $(document).height() - $(window).height()){
|
||||
$(window).unbind('scroll');
|
||||
CommitsList.getOld();
|
||||
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:
|
||||
function(count, html) {
|
||||
$("#commits_list").append(html);
|
||||
if(count > 0) {
|
||||
this.offset += count;
|
||||
this.initLoadMore();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
initLoadMore:
|
||||
function() {
|
||||
$(window).bind('scroll', function(){
|
||||
if($(window).scrollTop() == $(document).height() - $(window).height()){
|
||||
$(window).unbind('scroll');
|
||||
CommitsList.getOld();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,66 @@
|
|||
$(document).ready(function(){
|
||||
$("#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;
|
||||
var ProjectsList = {
|
||||
limit:0,
|
||||
offset:0,
|
||||
|
||||
init:
|
||||
function(limit) {
|
||||
this.limit=limit;
|
||||
this.offset=limit;
|
||||
this.initLoadMore();
|
||||
|
||||
$('.project_search').keyup(function() {
|
||||
var terms = $(this).val();
|
||||
if (terms.length >= 2 || terms.length == 0) {
|
||||
url = $('.project_search').parent().attr('action');
|
||||
$.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"});
|
||||
},
|
||||
|
||||
replace:
|
||||
function(count, html) {
|
||||
$(".tile").html(html);
|
||||
if(count == ProjectsList.limit) {
|
||||
this.offset = count;
|
||||
this.initLoadMore();
|
||||
} else {
|
||||
this.offset = 0;
|
||||
}
|
||||
},
|
||||
|
||||
append:
|
||||
function(count, html) {
|
||||
$(".tile").append(html);
|
||||
if(count > 0) {
|
||||
this.offset += count;
|
||||
this.initLoadMore();
|
||||
}
|
||||
},
|
||||
|
||||
initLoadMore:
|
||||
function() {
|
||||
$(window).bind('scroll', function(){
|
||||
if($(window).scrollTop() == $(document).height() - $(window).height()){
|
||||
$(window).unbind('scroll');
|
||||
$('.loading').show();
|
||||
ProjectsList.getOld();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#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;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -647,3 +647,9 @@ h4.middle-panel {
|
|||
border-radius:3px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.project_search {
|
||||
margin: 1.5em 0;
|
||||
padding: 8px !important;
|
||||
width: 300px;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ class DashboardController < ApplicationController
|
|||
|
||||
def index
|
||||
@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|
|
||||
format.html
|
||||
|
|
|
@ -11,9 +11,10 @@ class ProjectsController < ApplicationController
|
|||
before_filter :require_non_empty_project, :only => [:blob, :tree, :graph]
|
||||
|
||||
def index
|
||||
source = current_user.projects
|
||||
source = source.tagged_with(params[:tag]) unless params[:tag].blank?
|
||||
@projects = source.all
|
||||
@limit, @offset = (params[:limit] || 16), (params[:offset] || 0)
|
||||
@projects = current_user.projects
|
||||
@projects = @projects.where("name LIKE ?", "%#{params[:terms]}%") unless params[:terms].blank?
|
||||
@projects = @projects.limit(@limit).offset(@offset)
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -35,9 +35,8 @@ class MergeRequest < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def diffs
|
||||
commit = project.commit(source_branch)
|
||||
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
|
||||
|
||||
def last_commit
|
||||
|
|
|
@ -52,6 +52,9 @@ class Project < ActiveRecord::Base
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -195,6 +198,24 @@ class Project < ActiveRecord::Base
|
|||
last_activity.try(:created_at)
|
||||
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
|
||||
# or calculate.
|
||||
def cached_updates(limit, expire = 2.minutes)
|
||||
|
@ -204,7 +225,7 @@ class Project < ActiveRecord::Base
|
|||
activities = cached_activities
|
||||
else
|
||||
activities = updates(limit)
|
||||
Rails.cache.write(activities_key, activities, :expires_in => 60.seconds)
|
||||
Rails.cache.write(activities_key, activities, :expires_in => expire)
|
||||
end
|
||||
|
||||
activities
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
%span.project-name= project.name
|
||||
%span.time
|
||||
%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 @@
|
|||
ago
|
||||
.clear
|
||||
|
||||
- if @commits.empty?
|
||||
%p.cgray Nothing to merge
|
||||
|
|
|
@ -20,3 +20,5 @@
|
|||
%p
|
||||
%center No preview for this file type
|
||||
|
||||
- if @diffs.empty?
|
||||
%p.cgray Nothing to merge
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
%input{ :value => project.url_to_repo, :class => ['git-url', 'one_click_select', 'text', 'project_list_url'], :readonly => 'readonly' }
|
||||
%p.title.activity
|
||||
%span Last Activity:
|
||||
- last_note = project.notes.last
|
||||
= last_note ? last_note.created_at.stamp("24 Aug, 2011") : "Never"
|
||||
|
||||
%p.small-tags= tag_list project
|
||||
- if project.last_activity_date_cached
|
||||
= project.last_activity_date_cached.stamp("24 Aug, 2011")
|
||||
- else
|
||||
Never
|
||||
|
||||
.buttons
|
||||
%a.browse-code.button.yellow{:href => tree_project_ref_path(project, project.root_ref)} Browse code
|
||||
|
|
|
@ -7,13 +7,23 @@
|
|||
%h2.icon
|
||||
%span
|
||||
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
|
||||
- unless @projects.empty?
|
||||
%div{:class => "tile", :style => view_mode_style("tile")}
|
||||
%div{:class => "tile"}
|
||||
= render "tile"
|
||||
%div{:class => "list", :style => view_mode_style("list")}
|
||||
= render "list"
|
||||
.clear
|
||||
.loading{ :style => "display:none;"}
|
||||
%center= image_tag "ajax-loader.gif"
|
||||
|
||||
- if @projects.count == @limit
|
||||
:javascript
|
||||
$(function(){
|
||||
ProjectsList.init(16);
|
||||
});
|
||||
- else
|
||||
%center.prepend-top
|
||||
%h2
|
||||
|
|
7
app/views/projects/index.js.haml
Normal file
7
app/views/projects/index.js.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
- 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'))}");
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
#if defined?(Footnotes) && Rails.env.development?
|
||||
#Footnotes.run! # first of all
|
||||
|
||||
# ... other init code
|
||||
#end
|
||||
|
|
Loading…
Reference in a new issue