Pagination for history and latest changes. (#1396)

* Pagination for history and latest changes

* New footer for historical pages

* Fix pagination on history view.

* Do not directly use git adapter

* History view: allow selecting from different pages

* Use log_pagination_options to determine latest changes parameters

* Fix JS pageFullPath
This commit is contained in:
Dawa Ometto
2019-08-21 23:28:49 +02:00
committed by GitHub
parent 29a8b893f1
commit 976f55e1b2
18 changed files with 186 additions and 139 deletions
+16 -8
View File
@@ -17,6 +17,8 @@ require 'gollum/views/helpers'
require 'gollum/views/layout'
require 'gollum/views/editable'
require 'gollum/views/has_page'
require 'gollum/views/pagination'
require File.expand_path '../helpers', __FILE__
@@ -355,8 +357,7 @@ module Precious
else
sha2, sha1 = sha1, "#{sha1}^" if !sha2
@versions = [sha1, sha2]
diffs = wiki.repo.diff(@versions.first, @versions.last, @page.path)
@diff = diffs.first
@diff = wiki.full_reverse_diff_for(@page, @versions.first, @versions.last)
@message = "The patch does not apply."
mustache :compare
end
@@ -385,9 +386,15 @@ module Precious
wikip = wiki_page(params[:splat].first)
@name = wikip.fullname
@page = wikip.page
@page_num = [params[:page].to_i, 1].max
@page_num = [params[:page_num].to_i, 1].max
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
unless @page.nil?
@versions = @page.versions(:page => @page_num, :follow => settings.wiki_options.fetch(:follow_renames, ::Gollum::GIT_ADAPTER == 'rjgit' ? false : true))
@versions = @page.versions(
per_page: @max_count,
page_num: @page_num,
follow: settings.wiki_options.fetch(:follow_renames,
::Gollum::GIT_ADAPTER == 'rjgit' ? false : true)
)
mustache :history
else
redirect to("/")
@@ -396,8 +403,9 @@ module Precious
get '/latest_changes' do
@wiki = wiki_new
max_count = settings.wiki_options.fetch(:latest_changes_count, 10)
@versions = @wiki.latest_changes({:max_count => max_count})
@page_num = [params[:page_num].to_i, 1].max
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
@versions = @wiki.latest_changes(::Gollum::Page.log_pagination_options(per_page: @max_count, page_num: @page_num))
mustache :latest_changes
end
@@ -429,8 +437,7 @@ module Precious
@versions = [start_version, end_version]
wiki = wikip.wiki
@page = wikip.page
diffs = wiki.repo.diff(@versions.first, @versions.last, @page.path)
@diff = diffs.first
@diff = wiki.full_reverse_diff_for(@page, @versions.first, @versions.last)
mustache :compare
end
@@ -477,6 +484,7 @@ module Precious
@name = name
@content = page.formatted_data
@version = version
@historical = true
@bar_side = wikip.wiki.bar_side
@navbar = true
mustache :page
@@ -97,91 +97,6 @@ $(document).ready(function() {
e.preventDefault();
} );
var nodeSelector = {
node1: null,
node2: null,
selectNodeRange: function( n1, n2 ) {
if ( nodeSelector.node1 && nodeSelector.node2 ) {
$('#wiki-history td.selected').removeClass('selected');
nodeSelector.node1.addClass('selected');
nodeSelector.node2.addClass('selected');
// swap the nodes around if they went in reverse
if ( nodeSelector.nodeComesAfter( nodeSelector.node1,
nodeSelector.node2 ) ) {
var n = nodeSelector.node1;
nodeSelector.node1 = nodeSelector.node2;
nodeSelector.node2 = n;
}
var s = true;
var $nextNode = nodeSelector.node1.next();
while ( $nextNode ) {
$nextNode.addClass('selected');
if ( $nextNode[0] == nodeSelector.node2[0] ) {
break;
}
$nextNode = $nextNode.next();
}
}
},
nodeComesAfter: function ( n1, n2 ) {
var s = false;
$(n1).prevAll().each(function() {
if ( $(this)[0] == $(n2)[0] ) {
s = true;
}
});
return s;
},
checkNode: function( nodeCheckbox ) {
var $nodeCheckbox = nodeCheckbox;
var $node = $(nodeCheckbox).parent().parent();
// if we're unchecking
if ( !$nodeCheckbox.is(':checked') ) {
// remove the range, since we're breaking it
$('#wiki-history tr.selected').each(function() {
if ( $(this).find('td.checkbox input').is(':checked') ) {
return;
}
$(this).removeClass('selected');
});
// no longer track this
if ( $node[0] == nodeSelector.node1[0] ) {
nodeSelector.node1 = null;
if ( nodeSelector.node2 ) {
nodeSelector.node1 = nodeSelector.node2;
nodeSelector.node2 = null;
}
} else if ( $node[0] == nodeSelector.node2[0] ) {
nodeSelector.node2 = null;
}
} else {
if ( !nodeSelector.node1 ) {
nodeSelector.node1 = $node;
nodeSelector.node1.addClass('selected');
} else if ( !nodeSelector.node2 ) {
// okay, we don't have a node 2 but have a node1
nodeSelector.node2 = $node;
nodeSelector.node2.addClass('selected');
nodeSelector.selectNodeRange( nodeSelector.node1,
nodeSelector.node2 );
} else {
// we have two selected already
$nodeCheckbox[0].checked = false;
}
}
}
};
// ua detection
if ($.browser.mozilla) {
$('body').addClass('ff');
@@ -351,7 +266,7 @@ $(document).ready(function() {
if ($('.history button.action-compare-revision').length) {
$('.history button.action-compare-revision').click(function() {
$("#version-form").submit();
$("#selection-form").submit();
});
}
}
@@ -445,6 +360,99 @@ $(document).ready(function() {
});
}
if( $("#page-history").length) {
if( $("#page-history #pagination").length) {
var maxSelected = 2;
var selectionColors = ["bg-green-light", "bg-red-light"];
var toggleInputs = function () {
var numSelected = 0;
$("#selection-form input").each(function (index, element) {
var value = $(element).val();
var input = $('#version-form input[value="' + value + '"]');
input.prop('checked', true);
if (index == 0) {
input.closest("li").removeClass(selectionColors[1]).addClass(selectionColors[index]);
} else if (index == 1) {
input.closest("li").addClass(selectionColors[index]);
}
numSelected = numSelected + 1;
});
if (numSelected == maxSelected) {
$('#version-form input:not(:checked)').prop('disabled', true);
$('.history button.action-compare-revision').prop('disabled', false);
} else if (numSelected < maxSelected) {
$('#version-form input').prop('disabled', false);
$('.history button.action-compare-revision').prop('disabled', true);
}
};
var onCheckboxSelect = function ( box ) {
$('<input>').attr({
type: 'hidden',
id: $(box).val(),
name: 'versions[]',
value: $(box).val()
}).appendTo($("#selection-form"));
toggleInputs();
};
var onCheckboxUnselect = function( box ) {
$('#selection-form #' + $(box).val()).remove();
$(box).closest("li").removeClass(selectionColors.join(" "));
toggleInputs();
};
var setCheckboxEvents = function () {
$("#version-form input").on('change', function () {
if (this.checked) {
onCheckboxSelect(this);
} else {
onCheckboxUnselect(this);
}
});
};
setCheckboxEvents();
toggleInputs();
var clickPageNav = function (e) {
e.preventDefault();
$.ajax({
url: $(this).attr('href'),
type: 'GET',
success: function(data) {
var rowDiv = $('#page-history-list', data);
var new_pagination = $('#pagination', data);
next = $('#pagination #next');
prev = $('#pagination #prev');
new_next = new_pagination.find('#next');
new_prev = new_pagination.find('#prev');
next[0].hidden = new_next[0].hidden;
prev[0].hidden = new_prev[0].hidden;
next.children('a').attr('href', new_next.children('a').attr('href'));
prev.children('a').attr('href', new_prev.children('a').attr('href'));
$('#page-history-list').replaceWith(rowDiv);
setCheckboxEvents();
toggleInputs();
},
error: function(data, textStatus, errorThrown) {
console.log('something went wrong: ' + textStatus + errorThrown)
}
});
};
$("#pagination #next a, #pagination #prev a").each(function(index, element) {
$(element).on("click", clickPageNav);
});
}
}
if( $("#last-edit").length ) {
$("#page-info-toggle").click ( function () {
$.ajax({
@@ -726,4 +726,4 @@ a {
color: #A31515;
}
}
}
}
+7 -7
View File
@@ -1,16 +1,17 @@
<div id="wiki-wrapper" class="history">
<div id="head">
{{>navbar}}
<h1 class="py-4"><span class="f1-light text-gray-light"> History for</span> {{name}}</h1>
<h1 class="py-4"><span class="f1-light text-gray-light">History for</span> {{name}}</h1>
</div>
<div id="page-history">
<div class="pb-4"><button class="btn btn-sm action-compare-revision" type="submit">Compare Revisions</button></div>
{{>pagination}}
<div class="Box Box--condensed flex-auto">
<form name="compare-versions" id="version-form" method="post"
action="{{compare_path}}/{{escaped_url_path}}">
<ul>
<form name="selection-form" id="selection-form" method="post" action="{{compare_path}}/{{escaped_url_path}}"></form>
<div id="page-history-list" class="Box Box--condensed flex-auto">
<form id="version-form">
<ul>
{{#versions}}
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
@@ -30,6 +31,5 @@
<div class="pt-4">
<button class="btn btn-sm action-compare-revision" type="submit">Compare Revisions</button>
</div>
<div class="pt-2"><a href="#" class="action-back-to-top">Back to Top</a></div>
</div>
</div>
@@ -1,3 +1 @@
<a href="javascript:void(0)">
{{author}}
</a>
{{author}}
@@ -3,6 +3,9 @@
{{>navbar}}
<h1 class="py-4">{{title}}</h1>
</div>
{{>pagination}}
<div id="wiki-history">
<div class="Box flex-auto">
+1 -1
View File
@@ -21,7 +21,7 @@
uploadDest = uploadDest + window.location.pathname.replace(/.*gollum\/[-\w]+\//, "/").replace(/\.[^/.]+$/, "")
}
{{#page}}
var pageFullPath = '{{url_path.source_location}}';
var pageFullPath = '{{escaped_url_path}}';
{{/page}}
</script>
+11
View File
@@ -0,0 +1,11 @@
<div id="pagination" class="pb-2 px-3">
<span id="prev" {{^previous_page}}hidden{{/previous_page}}>
<a href="?page_num={{previous_page}}">&laquo; Previous</a>
</span>
<span>&nbsp;</span>
<span id="next" class="float-right" {{^next_page}}hidden{{/next_page}}>
<a href="?page_num={{next_page}}">Next &raquo;</a>
</span>
</div>
+7 -2
View File
@@ -42,15 +42,20 @@
<div id="footer" class="pt-4">
{{^historical}}
{{^preview}}
<p id="last-edit"><a id="page-info-toggle" data-pagepath="{{escaped_url_path}}">When was this page last modified?</a></p>
{{#allow_editing}}
<p>
<a id="delete-link" href="{{escaped_url_path}}" data-confirm="Are you sure you want to delete this page?"><span>Delete this Page</span></a>
</p>
{{/allow_editing}}
{{/allow_editing}}
{{/preview}}
{{/historical}}
{{#historical}}
<p>This version of the page was edited by <b>{{author}}</b> at {{date}}. <a href="{{full_url_path}}">View the most recent version.</a></p>
{{/historical}}
</div>
</div>
</div>
+1 -1
View File
@@ -19,7 +19,7 @@ module Precious
def lines
lines = []
@diff.diff.split("\n")[2..-1].each_with_index do |line, line_index|
@diff.split("\n")[2..-1].each_with_index do |line, line_index|
lines << { :line => line,
:class => line_class(line),
:ldln => left_diff_line_number(0, line),
+4
View File
@@ -15,5 +15,9 @@ module Precious
def id
@page.sha
end
def full_url_path
::File.join(@base_url, escaped_url_path)
end
end
end
+2 -21
View File
@@ -2,10 +2,11 @@ module Precious
module Views
class History < Layout
include HasPage
include Pagination
include Sprockets::Helpers
include Precious::Views::SprocketsHelpers
attr_reader :page, :page_num, :allow_editing
attr_reader :page, :allow_editing
def title
@page.title
@@ -69,26 +70,6 @@ module Precious
def editable
@editable
end
def previous_link
label = "&laquo; Previous"
if @page_num == 1
%(<span class="disabled">#{label}</span>)
else
link = url("/history/#{@page.name}?page=#{@page_num-1}")
%(<a href="#{link}" hotkey="h">#{label}</a>)
end
end
def next_link
label = "Next &raquo;"
if @versions.size == Gollum::Page.per_page
link = "/history/#{@page.name}?page=#{@page_num+1}"
%(<a href="#{link}" hotkey="l">#{label}</a>)
else
%(<span class="disabled">#{label}</span>)
end
end
end
end
end
+1
View File
@@ -1,6 +1,7 @@
module Precious
module Views
class LatestChanges < Layout
include Pagination
attr_reader :wiki
+1 -1
View File
@@ -1,4 +1,4 @@
require "pathname"
require 'pathname'
module Precious
module Views
+3 -3
View File
@@ -3,7 +3,7 @@ module Precious
class Page < Layout
include HasPage
attr_reader :content, :page, :header, :footer, :preview
attr_reader :content, :page, :header, :footer, :preview, :historical
VALID_COUNTER_STYLES = ['decimal', 'decimal-leading-zero', 'arabic-indic', 'armenian', 'upper-armenian',
'lower-armenian', 'bengali', 'cambodian', 'khmer', 'cjk-decimal', 'devanagari', 'georgian', 'gujarati', 'gurmukhi',
@@ -42,13 +42,13 @@ module Precious
end
def author
first = page.last_version
first = @version ? page.version : page.last_version
return DEFAULT_AUTHOR unless first
first.author.name.respond_to?(:force_encoding) ? first.author.name.force_encoding('UTF-8') : first.author.name
end
def date
first = page.last_version
first = @version ? page.version : page.last_version
return Time.now.strftime(DATE_FORMAT) unless first
first.authored_date.strftime(DATE_FORMAT)
end
+11
View File
@@ -0,0 +1,11 @@
module Precious
module Pagination
def next_page
@versions.length < @max_count ? nil : (@page_num + 1).to_s
end
def previous_page
@page_num == 1 ? nil : (@page_num - 1).to_s
end
end
end
+17
View File
@@ -701,6 +701,23 @@ context "Frontend with lotr" do
assert_match /not so big smelly creatures/, last_response.body
end
test 'editable pages have footer' do
get 'Bilbo-Baggings'
assert_equal last_response.body.include?('delete-link'), false
assert_equal last_response.body.include?('page-info-toggle'), false
end
test 'show specific revision of page' do
old_sha = '5bc1aaec6149e854078f1d0f8b71933bbc6c2e43'
page = 'Bilbo-Baggins'
get "#{page}/#{old_sha}"
assert last_response.ok?
assert_equal last_response.body.include?('delete-link'), false
assert_equal last_response.body.include?('page-info-toggle'), false
assert last_response.body.include?('This version of the page was edited by <b>Tom Preston-Werner</b> at 2010-04-07')
assert last_response.body.include?("<a href=\"/Bilbo-Baggins.md\">View the most recent version.</a></p>")
end
test "show revision of specific file" do
old_sha = "df26e61e707116f81ebc6b935ec6d1676b7e96c4"
update_sha = "f803c64d11407b23797325e3843f3f378b78f611"
+5 -5
View File
@@ -13,16 +13,16 @@ context "Precious::Views::LatestChanges" do
@path = cloned_testpath("examples/lotr.git")
@wiki = Gollum::Wiki.new(@path)
Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {:latest_changes_count => 10})
Precious::App.set(:wiki_options, {:pagination_count => 10})
end
test "displays_latest_changes" do
get('/gollum/latest_changes')
body = last_response.body
assert body.include?("<span class=\"float-left col-2\"><a href=\"javascript:void(0)\">\n Charles Pence\n</a>\n</span>"), "/latest_changes should include Author Charles Pence"
assert body.include?('1db89eb'), "/latest_changes should include the :latest_changes_count commit"
assert !body.include?('a8ad3c0'), "/latest_changes should not include more than latest_changes_count commits"
assert body.include?("Charles Pence</span>"), "/latest_changes should include Author Charles Pence"
assert body.include?('1db89eb'), "/latest_changes should include the :pagination_count commit"
assert !body.include?('a8ad3c0'), "/latest_changes should not include more than :pagination_count commits"
assert body.include?('<a href="Data-Two.csv/874f597a5659b4c3b153674ea04e406ff393975e">Data-Two.csv</a>'), "/latest_changes include links to modified files in #{body}"
assert body.include?('<a href="Hobbit.md/874f597a5659b4c3b153674ea04e406ff393975e">Hobbit.md</a>'), "/latest_changes should include links to modified pages in #{body}"
end