summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandx <dmitriy.zaporozhets@gmail.com>2012-07-10 22:52:38 +0300
committerrandx <dmitriy.zaporozhets@gmail.com>2012-07-10 22:52:38 +0300
commit1a2bacfb4b4b8f4d79df0335b4daf1d2cfa16d88 (patch)
tree980046192fa8c9db035936321f9e07ccdcde0814
parentb8425cf173841eb2f7ba95141f364241a81a52a8 (diff)
downloadgitlab-ce-1a2bacfb4b4b8f4d79df0335b4daf1d2cfa16d88.tar.gz
Feature: ajax load for tree commit log
-rw-r--r--app/assets/javascripts/application.js1
-rw-r--r--app/controllers/refs_controller.rb23
-rw-r--r--app/views/refs/_tree.html.haml13
-rw-r--r--app/views/refs/_tree_commit.html.haml3
-rw-r--r--app/views/refs/_tree_item.html.haml18
-rw-r--r--app/views/refs/logs_tree.js.haml9
-rw-r--r--app/views/refs/tree.js.haml5
-rw-r--r--config/routes.rb10
-rw-r--r--vendor/assets/javascripts/jquery.waitforimages.js144
9 files changed, 206 insertions, 20 deletions
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 683d8fa80b4..4815d180dfb 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -12,6 +12,7 @@
//= require jquery.cookie
//= require jquery.endless-scroll
//= require jquery.highlight
+//= require jquery.waitforimages
//= require bootstrap-modal
//= require modernizr
//= require chosen-jquery
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index ddf5f675d0c..b610c9f34d4 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -9,7 +9,7 @@ class RefsController < ApplicationController
before_filter :require_non_empty_project
before_filter :ref
- before_filter :define_tree_vars, :only => [:tree, :blob, :blame]
+ before_filter :define_tree_vars, :only => [:tree, :blob, :blame, :logs_tree]
before_filter :render_full_content
layout "project"
@@ -46,6 +46,18 @@ class RefsController < ApplicationController
end
end
+ def logs_tree
+ contents = @tree.contents
+ @logs = contents.map do |content|
+ file = params[:path] ? File.join(params[:path], content.name) : content.name
+ last_commit = @project.commits(@commit.id, file, 1).last
+ {
+ :file_name => content.name,
+ :commit => last_commit
+ }
+ end
+ end
+
def blob
if @tree.is_blob?
if @tree.text?
@@ -79,6 +91,15 @@ class RefsController < ApplicationController
@commit = project.commit(@ref)
@tree = Tree.new(@commit.tree, project, @ref, params[:path])
@tree = TreeDecorator.new(@tree)
+ @hex_path = Digest::SHA1.hexdigest(params[:path] || "/")
+
+ if params[:path]
+ @history_path = tree_file_project_ref_path(@project, @ref, params[:path])
+ @logs_path = logs_file_project_ref_path(@project, @ref, params[:path])
+ else
+ @history_path = tree_project_ref_path(@project, @ref)
+ @logs_path = logs_tree_project_ref_path(@project, @ref)
+ end
rescue
return render_404
end
diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml
index 4450afdfa3e..1965fe45b36 100644
--- a/app/views/refs/_tree.html.haml
+++ b/app/views/refs/_tree.html.haml
@@ -13,7 +13,7 @@
= render :partial => "refs/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree }
- else
- contents = tree.contents
- %table#tree-slider.bordered-table.table
+ %table#tree-slider.bordered-table.table{:class => "table_#{@hex_path}" }
%thead
%th Name
%th Last Update
@@ -48,17 +48,18 @@
- else
= simple_format(content.data)
-- if params[:path]
- - history_path = tree_file_project_ref_path(@project, @ref, params[:path])
-- else
- - history_path = tree_project_ref_path(@project, @ref)
:javascript
$(function(){
$('select#branch').selectmenu({style:'popup', width:200});
$('select#tag').selectmenu({style:'popup', width:200});
$('.project-refs-select').chosen();
- history.pushState({ path: this.path }, '', "#{history_path}")
+ history.pushState({ path: this.path }, '', "#{@history_path}");
+
+ });
+
+ $(window).load(function(){
+ $.ajax({type: "GET", url: '#{@logs_path}', dataType: "script"});
});
diff --git a/app/views/refs/_tree_commit.html.haml b/app/views/refs/_tree_commit.html.haml
new file mode 100644
index 00000000000..1f2524a4c3a
--- /dev/null
+++ b/app/views/refs/_tree_commit.html.haml
@@ -0,0 +1,3 @@
+- if tm
+ %strong= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm)
+= link_to truncate(content_commit.safe_message, :length => tm ? 30 : 50), project_commit_path(@project, content_commit.id), :class => "tree-commit-link"
diff --git a/app/views/refs/_tree_item.html.haml b/app/views/refs/_tree_item.html.haml
index 45ea53718c0..30331944a7f 100644
--- a/app/views/refs/_tree_item.html.haml
+++ b/app/views/refs/_tree_item.html.haml
@@ -1,23 +1,15 @@
- file = params[:path] ? File.join(params[:path], content.name) : content.name
-- content_commit = @project.commits(@commit.id, file, 1).last
-- return unless content_commit
-%tr{ :class => "tree-item", :url => tree_file_project_ref_path(@project, @ref, file) }
+%tr{ :class => "tree-item file_#{Digest::SHA1.hexdigest(content.name)}", :url => tree_file_project_ref_path(@project, @ref, file) }
%td.tree-item-file-name
- if content.is_a?(Grit::Blob)
- if content.text?
- = image_tag "file_txt.png"
+ = image_tag "file_txt.png", :class => "tree-ico"
- elsif content.image?
- = image_tag "file_img.png"
+ = image_tag "file_img.png", :class => "tree-ico"
- else
- = image_tag "file_bin.png"
+ = image_tag "file_bin.png", :class => "tree-ico"
- else
- = image_tag "file_dir.png"
+ = image_tag "file_dir.png", :class => "tree-ico"
= link_to truncate(content.name, :length => 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), :remote => :true
%td.tree_time_ago.cgray
- = time_ago_in_words(content_commit.committed_date)
- ago
%td.tree_commit
- - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name)
- - if tm
- %strong= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm)
- = link_to truncate(content_commit.safe_message, :length => tm ? 30 : 50), project_commit_path(@project, content_commit.id), :class => "tree-commit-link"
diff --git a/app/views/refs/logs_tree.js.haml b/app/views/refs/logs_tree.js.haml
new file mode 100644
index 00000000000..ea8337398a4
--- /dev/null
+++ b/app/views/refs/logs_tree.js.haml
@@ -0,0 +1,9 @@
+- @logs.each do |content_data|
+ - file_name = content_data[:file_name]
+ - content_commit = content_data[:commit]
+ - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name)
+
+ :plain
+ var row = $("table.table_#{@hex_path} tr.file_#{Digest::SHA1.hexdigest(file_name)}");
+ row.find("td.tree_time_ago").html('#{escape_javascript(time_ago_in_words(content_commit.committed_date))} ago');
+ row.find("td.tree_commit").html('#{escape_javascript(render("tree_commit", :tm => tm, :content_commit => content_commit))}');
diff --git a/app/views/refs/tree.js.haml b/app/views/refs/tree.js.haml
index f4f28adc369..600ba62606e 100644
--- a/app/views/refs/tree.js.haml
+++ b/app/views/refs/tree.js.haml
@@ -2,3 +2,8 @@
$("#tree-holder").html("#{escape_javascript(render(:partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree}))}");
$("#tree-content-holder").show("slide", { direction: "right" }, 150);
$('.project-refs-form #path').val("#{params[:path]}");
+
+
+ $('#tree-slider').waitForImages(function() {
+ $.ajax({type: "GET", url: '#{@logs_path}', dataType: "script"});
+ });
diff --git a/config/routes.rb b/config/routes.rb
index 3b33ed8dfd1..73b9f643ad5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -117,6 +117,8 @@ Gitlab::Application.routes.draw do
member do
get "tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
+ get "logs_tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
+
get "blob",
:constraints => {
:id => /[a-zA-Z.0-9\/_\-]+/,
@@ -132,6 +134,14 @@ Gitlab::Application.routes.draw do
:path => /.*/
}
+ # tree viewer
+ get "logs_tree/:path" => "refs#logs_tree",
+ :as => :logs_file,
+ :constraints => {
+ :id => /[a-zA-Z.0-9\/_\-]+/,
+ :path => /.*/
+ }
+
# blame
get "blame/:path" => "refs#blame",
:as => :blame_file,
diff --git a/vendor/assets/javascripts/jquery.waitforimages.js b/vendor/assets/javascripts/jquery.waitforimages.js
new file mode 100644
index 00000000000..95b39c2e074
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.waitforimages.js
@@ -0,0 +1,144 @@
+/*
+ * waitForImages 1.4
+ * -----------------
+ * Provides a callback when all images have loaded in your given selector.
+ * http://www.alexanderdickson.com/
+ *
+ *
+ * Copyright (c) 2011 Alex Dickson
+ * Licensed under the MIT licenses.
+ * See website for more info.
+ *
+ */
+
+;(function($) {
+ // Namespace all events.
+ var eventNamespace = 'waitForImages';
+
+ // CSS properties which contain references to images.
+ $.waitForImages = {
+ hasImageProperties: [
+ 'backgroundImage',
+ 'listStyleImage',
+ 'borderImage',
+ 'borderCornerImage'
+ ]
+ };
+
+ // Custom selector to find `img` elements that have a valid `src` attribute and have not already loaded.
+ $.expr[':'].uncached = function(obj) {
+ // Ensure we are dealing with an `img` element with a valid `src` attribute.
+ if ( ! $(obj).is('img[src!=""]')) {
+ return false;
+ }
+
+ // Firefox's `complete` property will always be`true` even if the image has not been downloaded.
+ // Doing it this way works in Firefox.
+ var img = document.createElement('img');
+ img.src = obj.src;
+ return ! img.complete;
+ };
+
+ $.fn.waitForImages = function(finishedCallback, eachCallback, waitForAll) {
+
+ // Handle options object.
+ if ($.isPlainObject(arguments[0])) {
+ eachCallback = finishedCallback.each;
+ waitForAll = finishedCallback.waitForAll;
+ finishedCallback = finishedCallback.finished;
+ }
+
+ // Handle missing callbacks.
+ finishedCallback = finishedCallback || $.noop;
+ eachCallback = eachCallback || $.noop;
+
+ // Convert waitForAll to Boolean
+ waitForAll = !! waitForAll;
+
+ // Ensure callbacks are functions.
+ if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) {
+ throw new TypeError('An invalid callback was supplied.');
+ };
+
+ return this.each(function() {
+ // Build a list of all imgs, dependent on what images will be considered.
+ var obj = $(this),
+ allImgs = [];
+
+ if (waitForAll) {
+ // CSS properties which may contain an image.
+ var hasImgProperties = $.waitForImages.hasImageProperties || [],
+ matchUrl = /url\((['"]?)(.*?)\1\)/g;
+
+ // Get all elements, as any one of them could have a background image.
+ obj.find('*').each(function() {
+ var element = $(this);
+
+ // If an `img` element, add it. But keep iterating in case it has a background image too.
+ if (element.is('img:uncached')) {
+ allImgs.push({
+ src: element.attr('src'),
+ element: element[0]
+ });
+ }
+
+ $.each(hasImgProperties, function(i, property) {
+ var propertyValue = element.css(property);
+ // If it doesn't contain this property, skip.
+ if ( ! propertyValue) {
+ return true;
+ }
+
+ // Get all url() of this element.
+ var match;
+ while (match = matchUrl.exec(propertyValue)) {
+ allImgs.push({
+ src: match[2],
+ element: element[0]
+ });
+ };
+ });
+ });
+ } else {
+ // For images only, the task is simpler.
+ obj
+ .find('img:uncached')
+ .each(function() {
+ allImgs.push({
+ src: this.src,
+ element: this
+ });
+ });
+ };
+
+ var allImgsLength = allImgs.length,
+ allImgsLoaded = 0;
+
+ // If no images found, don't bother.
+ if (allImgsLength == 0) {
+ finishedCallback.call(obj[0]);
+ };
+
+ $.each(allImgs, function(i, img) {
+
+ var image = new Image;
+
+ // Handle the image loading and error with the same callback.
+ $(image).bind('load.' + eventNamespace + ' error.' + eventNamespace, function(event) {
+ allImgsLoaded++;
+
+ // If an error occurred with loading the image, set the third argument accordingly.
+ eachCallback.call(img.element, allImgsLoaded, allImgsLength, event.type == 'load');
+
+ if (allImgsLoaded == allImgsLength) {
+ finishedCallback.call(obj[0]);
+ return false;
+ };
+
+ });
+
+ image.src = img.src;
+ });
+ });
+ };
+})(jQuery);