New and Rename buttons now support directories

* Also fixes renaming a file from a subdirectory moves it to the root.
  * Add context info option to dialog, used in the new dialog
  * Added CSS to support new context option for dialogs
  * Fix /pages view messing up directory creation in new
  * Removed the Edit and Rename buttons from historic view
This commit is contained in:
Daniel Kimsey
2012-11-30 13:18:42 -05:00
parent 443c453507
commit 8fd8a56893
16 changed files with 413 additions and 35 deletions
+37 -6
View File
@@ -143,25 +143,57 @@ module Precious
end
end
post '/rename/*' do
wikip = wiki_page(params[:splat].first)
halt 500 if wikip.nil?
wiki = wikip.wiki
page = wiki.paged(wikip.name, wikip.path, exact = true)
rename = params[:rename]
halt 500 if page.nil?
halt 500 if rename.nil? or rename.empty?
# Fixup the rename if it is a relative path
# In 1.8.7 rename[0] != rename[0..0]
if rename[0..0] != '/'
source_dir = ::File.dirname(page.path)
source_dir = '' if source_dir == '.'
(target_dir, target_name) = ::File.split(rename)
target_dir = target_dir == '' ? source_dir : "#{source_dir}/#{target_dir}"
rename = "#{target_dir}/#{target_name}"
end
committer = Gollum::Committer.new(wiki, commit_message)
commit = {:committer => committer}
success = wiki.rename_page(page, rename, commit)
if !success
# This occurs on NOOPs, for example renaming A => A
redirect to("/#{page.escaped_url_path}")
return
end
committer.commit
wikip = wiki_page(rename)
page = wiki.paged(wikip.name, wikip.path, exact = true)
return if page.nil?
redirect to("/#{page.escaped_url_path}")
end
post '/edit/*' do
path = '/' + clean_url(sanitize_empty_params(params[:path])).to_s
page_name = CGI.unescape(params[:page])
wiki = wiki_new
page = wiki.paged(page_name, path, exact = true)
return if page.nil?
rename = params[:rename].to_url if params[:rename]
name = rename || page.name
committer = Gollum::Committer.new(wiki, commit_message)
commit = {:committer => committer}
update_wiki_page(wiki, page, params[:content], commit, name, params[:format])
update_wiki_page(wiki, page, params[:content], commit, page.name, params[:format])
update_wiki_page(wiki, page.header, params[:header], commit) if params[:header]
update_wiki_page(wiki, page.footer, params[:footer], commit) if params[:footer]
update_wiki_page(wiki, page.sidebar, params[:sidebar], commit) if params[:sidebar]
committer.commit
page = wiki.page(rename) if rename
redirect to("/#{page.escaped_url_path}") unless page.nil?
end
@@ -298,7 +330,6 @@ module Precious
@page = page
@name = name
@content = page.formatted_data
@editable = true
mustache :page
else
halt 404
@@ -87,6 +87,16 @@
font-family: 'Monaco', 'Courier New', Courier, monospace;
}
#gollum-dialog-dialog-body fieldset .field span.context {
font-size: .9em;
color: #666;
}
#gollum-dialog-dialog-body fieldset .field span.context span.path {
font-family: 'Monaco', 'Courier New', Courier, monospace;
font-weight: bold;
}
#gollum-dialog-dialog-body fieldset .field:last-child {
margin: 0 0 1em 0;
}
@@ -138,4 +148,4 @@
filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#599bdc', endColorstr='#3072b3');
background: -webkit-gradient(linear, left top, left bottom, from(#599bdc), to(#3072b3));
background: -moz-linear-gradient(top, #599bdc, #3072b3);
}
}
@@ -79,6 +79,10 @@
fieldAttributes.id + '">';
}
if( fieldAttributes.context ){
html += '<span class="context">' + fieldAttributes.context + '</span>';
}
return html;
},
@@ -1,10 +1,44 @@
// Helpers
function pageName(){
// "my/dir/file" => "file"
return typeof(pageFullPath) == 'undefined' ? undefined : pageFullPath.split('/').pop();
}
function pagePath(){
// "my/dir/file" => "my/dir"
return typeof(pageFullPath) == 'undefined' ? undefined : pageFullPath.split('/').slice(0,-1).join('/');
}
// Generic HTML escape function
function htmlEscape( str ) {
// The (slower) alternative is: return $('<div/>').text(str).html();
// http://stackoverflow.com/questions/1219860/javascript-jquery-html-encoding/7124052#7124052
return String(str)
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
// Given a page name and a current path, returns a fully qualified path.
function abspath(path, name){
// Make sure the given path starts at the root.
if(name[0] != '/'){
name = '/' + path + '/' + name;
}
var name_parts = name.split('/');
var newPath = name_parts.slice(0, -1).join('/');
var newName = name_parts.pop();
// return array of [path, name]
return [newPath, newName];
}
// ua
$(document).ready(function() {
$('#delete-link').click( function(e) {
var ok = confirm($(this).data('confirm'));
if ( ok ) {
var loc = window.location;
loc = baseUrl + '/delete' + loc.pathname.replace(baseUrl,'');
var loc = baseUrl + '/delete/' + pageFullPath;
window.location = loc;
}
// Don't navigate on cancel.
@@ -113,11 +147,12 @@ $(document).ready(function() {
$('#minibutton-rename-page').click(function(e) {
e.preventDefault();
// Path name without the leading slash.
var pathname = window.location.pathname.substr(1);
var slashIndex = pathname.lastIndexOf('/');
var oldName = pathname.substr(slashIndex + 1)
var path = pathname.substr(0, slashIndex);
var path = pagePath();
var oldName = pageName();
var context_blurb =
"Renamed page will be under " +
"<span class='path'>" + htmlEscape('/' + path) + "</span>" +
" unless an absolute path is given."
$.GollumDialog.init({
title: 'Rename Page',
@@ -126,7 +161,8 @@ $(document).ready(function() {
id: 'name',
name: 'Rename to',
type: 'text',
defaultValue: oldName || ''
defaultValue: oldName || '',
context: context_blurb
}
],
OK: function( res ) {
@@ -134,16 +170,17 @@ $(document).ready(function() {
if ( res['name'] ) {
newName = res['name'];
}
var name_parts = abspath(path, newName);
var newPath = name_parts[0];
var msg = 'Renamed ' + oldName + ' to ' + newName;
jQuery.ajax( {
type: 'POST',
url: baseUrl + '/edit/' + oldName,
data: { path: path, rename: newName, page: oldName, message: msg },
success: function() {
window.location = baseUrl + '/' + encodeURIComponent(newName);
}
});
var msg = '/' + path == newPath ? 'Renamed ' + oldName + ' to ' + newName
: 'Renamed ' + oldName + ' to ' + name_parts.join('/');
// Fill in the rename form
// This is preferable to AJAX so that we automatically follow the 302 response.
var rename_form = $("form[name=rename]");
rename_form.children("input[name=rename]").val(name_parts.join('/'));
rename_form.children("input[name=message]").val(msg);
rename_form.submit();
}
});
});
@@ -154,6 +191,23 @@ $(document).ready(function() {
$('#minibutton-new-page').click(function(e) {
e.preventDefault();
var path = pagePath();
if( path === undefined && $('#file-browser').length != 0 ){
// In the pages view, pageFullPath isn't defined.
// The new button will still expect a value however.
// So we try to figure one out from window.location
path = baseUrl == '' ? window.location.pathname.substr(1)
: window.location.pathname.substr(baseUrl.length + 1);
// Remove the page viewer part of the url.
path = path.replace(/^pages\/?/,'')
// For consistency remove the trailing /
path = path.replace(/\/$/,'')
}
var context_blurb =
"Page will be created under " +
"<span class='path'>" + htmlEscape('/' + path) + "</span>" +
" unless an absolute path is given."
$.GollumDialog.init({
title: 'Create New Page',
fields: [
@@ -161,7 +215,8 @@ $(document).ready(function() {
id: 'name',
name: 'Page Name',
type: 'text',
defaultValue: ''
defaultValue: '',
context: context_blurb
}
],
OK: function( res ) {
@@ -169,7 +224,13 @@ $(document).ready(function() {
if ( res['name'] ) {
name = res['name'];
}
window.location = baseUrl + '/' + encodeURIComponent(name);
var name_encoded = [];
var name_parts = abspath(path, name).join('/').split('/');
// Split and encode each component individually.
for( var i=0; i < name_parts.length; i++ ){
name_encoded.push(encodeURIComponent(name_parts[i]));
}
window.location = baseUrl + name_encoded.join('/');
}
});
});
@@ -12,7 +12,12 @@
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/ie7.css" media="all">
<![endif]-->
<script>var baseUrl = '{{base_url}}'</script>
<script>
var baseUrl = '{{base_url}}';
{{#page}}
var pageFullPath = '{{url_path}}';
{{/page}}
</script>
<script type="text/javascript" src="{{base_url}}/javascript/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="{{base_url}}/javascript/mousetrap.min.js"></script>
<script type="text/javascript" src="{{base_url}}/javascript/gollum.js"></script>
+6 -1
View File
@@ -20,9 +20,9 @@ Mousetrap.bind(['e'], function( e ) {
class="action-all-pages">Files</a></li>
<li class="minibutton" class="jaws">
<a href="#" id="minibutton-new-page">New</a></li>
{{#editable}}
<li class="minibutton" class="jaws">
<a href="#" id="minibutton-rename-page">Rename</a></li>
{{#editable}}
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit</a></li>
{{/editable}}
@@ -73,3 +73,8 @@ Mousetrap.bind(['e'], function( e ) {
</p>
</div>
</div>
<form name="rename" method="POST" action="{{base_url}}/rename/{{escaped_url_path}}">
<input type="hidden" name="rename"/>
<input type="hidden" name="message"/>
</from>
+56
View File
@@ -312,6 +312,62 @@ module Gollum
multi_commit ? committer : committer.commit
end
# Public: Rename an existing page without altering content.
#
# page - The Gollum::Page to update.
# rename - The String extension-less full path of the page (leading '/' is ignored).
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Grit::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
# Returns false if the operation is a NOOP.
def rename_page(page, rename, commit = {})
return false if page.nil?
return false if rename.nil? or rename.empty?
(target_dir, target_name) = ::File.split(rename)
(source_dir, source_name) = ::File.split(page.path)
source_name = page.filename_stripped
# File.split gives us relative paths with ".", commiter.add_to_index doesn't like that.
target_dir = '' if target_dir == '.'
source_dir = '' if source_dir == '.'
target_dir = target_dir.gsub(/^\//, '')
# if the rename is a NOOP, abort
if source_dir == target_dir and source_name == target_name
return false
end
multi_commit = false
committer = if obj = commit[:committer]
multi_commit = true
obj
else
Committer.new(self, commit)
end
committer.delete(page.path)
committer.add_to_index(target_dir, target_name, page.format, page.raw_data, :allow_same_ext)
committer.after_commit do |index, sha|
@access.refresh
index.update_working_dir(source_dir, source_name, page.format)
index.update_working_dir(target_dir, target_name, page.format)
end
multi_commit ? committer : committer.commit
end
# Public: Update an existing page with new content. The location of the
# page inside the repository will not change. If the given format is
# different than the current format of the page, the filename will be