Merge branch 'master' into close-accounts

This commit is contained in:
r888888888
2013-05-16 14:16:47 -07:00
129 changed files with 55250 additions and 462 deletions

View File

@@ -6,7 +6,9 @@ group :test do
gem "mocha", :require => "mocha/setup" gem "mocha", :require => "mocha/setup"
gem "ffaker", :git => "http://github.com/EmmanuelOga/ffaker.git" gem "ffaker", :git => "http://github.com/EmmanuelOga/ffaker.git"
gem "simplecov", :require => false gem "simplecov", :require => false
gem "testrbl" gem "pry"
gem "vcr"
gem "fakeweb"
end end
group :assets do group :assets do

View File

@@ -87,6 +87,7 @@ GEM
multi_json (~> 1.0) multi_json (~> 1.0)
factory_girl (4.2.0) factory_girl (4.2.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
fakeweb (1.3.0)
highline (1.6.18) highline (1.6.18)
hike (1.2.1) hike (1.2.1)
i18n (0.6.4) i18n (0.6.4)
@@ -178,7 +179,6 @@ GEM
rack (~> 1.0) rack (~> 1.0)
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
term-ansicolor (1.1.4) term-ansicolor (1.1.4)
testrbl (0.2.0)
therubyracer (0.11.4) therubyracer (0.11.4)
libv8 (~> 3.11.8.12) libv8 (~> 3.11.8.12)
ref ref
@@ -198,6 +198,7 @@ GEM
kgio (~> 2.6) kgio (~> 2.6)
rack rack
raindrops (~> 0.7) raindrops (~> 0.7)
vcr (2.4.0)
webrobots (0.1.1) webrobots (0.1.1)
whenever (0.8.2) whenever (0.8.2)
activesupport (>= 2.3.4) activesupport (>= 2.3.4)
@@ -217,6 +218,7 @@ DEPENDENCIES
delayed_job_active_record delayed_job_active_record
diff-lcs diff-lcs
factory_girl factory_girl
fakeweb
ffaker! ffaker!
mechanize! mechanize!
memcache-client memcache-client
@@ -236,8 +238,8 @@ DEPENDENCIES
simple_form simple_form
simplecov simplecov
term-ansicolor term-ansicolor
testrbl
therubyracer therubyracer
uglifier (>= 1.0.3) uglifier (>= 1.0.3)
unicorn unicorn
vcr
whenever whenever

View File

@@ -32,7 +32,7 @@
} }
Danbooru.Blacklist.toggle_entry = function(e) { Danbooru.Blacklist.toggle_entry = function(e) {
var tags = $(e.target).html(); var tags = $(e.target).text();
var match = $.grep(Danbooru.Blacklist.entries, function(entry, i) { var match = $.grep(Danbooru.Blacklist.entries, function(entry, i) {
return entry.tags === tags; return entry.tags === tags;
})[0]; })[0];
@@ -57,7 +57,7 @@
var link = $("<a/>"); var link = $("<a/>");
var count = $("<span/>"); var count = $("<span/>");
link.html(entry.tags); link.text(entry.tags);
link.click(Danbooru.Blacklist.toggle_entry); link.click(Danbooru.Blacklist.toggle_entry);
count.html(entry.hits); count.html(entry.hits);
item.append(link); item.append(link);

View File

@@ -15,6 +15,11 @@ $(function() {
Danbooru.Cookie.put('hide_upgrade_account_notice', '1', 7); Danbooru.Cookie.put('hide_upgrade_account_notice', '1', 7);
e.preventDefault(); e.preventDefault();
}); });
$("#close-notice-link").click(function(e) {
$('#notice').fadeOut("fast");
e.preventDefault();
});
}); });
var Danbooru = {}; var Danbooru = {};

View File

@@ -7,6 +7,9 @@
} }
Danbooru.Dtext.call_preview = function(e, $button, $input, $preview) { Danbooru.Dtext.call_preview = function(e, $button, $input, $preview) {
$button.val("Edit");
$input.hide();
$preview.text("Loading...").fadeIn("fast");
$.ajax({ $.ajax({
type: "post", type: "post",
url: "/dtext_preview", url: "/dtext_preview",
@@ -14,8 +17,6 @@
body: $input.val() body: $input.val()
}, },
success: function(data) { success: function(data) {
$button.val("Edit");
$input.hide();
$preview.html(data).fadeIn("fast"); $preview.html(data).fadeIn("fast");
} }
}); });

View File

@@ -2,9 +2,9 @@
Danbooru.NewsUpdate = {}; Danbooru.NewsUpdate = {};
Danbooru.NewsUpdate.initialize = function() { Danbooru.NewsUpdate.initialize = function() {
var key = $("#news-updates").data("updated-at"); var key = $("#news-updates").data("id");
if (Danbooru.Cookie.get("news-ticker") === key) { if (Danbooru.Cookie.get("news-ticker") == key) {
$("#news-updates").hide(); $("#news-updates").hide();
} else { } else {
$("#close-news-ticker-link").click(function(e) { $("#close-news-ticker-link").click(function(e) {
@@ -12,7 +12,8 @@
Danbooru.Cookie.put("news-ticker", key); Danbooru.Cookie.put("news-ticker", key);
// need to reset the more link // need to reset the more link
$("#more-links").hide().offset({top: $("#site-map-link").offset().top + $("#site-map-link").height() + 10, left: $("#site-map-link").offset().left}); var $site_map_link = $("#site-map-link");
$("#more-links").hide().offset({top: $site_map_link.offset().top + $site_map_link.height() + 10, left: $site_map_link.offset().left});
return false; return false;
}); });

View File

@@ -66,8 +66,18 @@ Danbooru.Note = {
var $note_box_inner = $(e.currentTarget); var $note_box_inner = $(e.currentTarget);
if (e.type === "mouseover") { if (e.type === "mouseover") {
Danbooru.Note.Body.show($note_box_inner.data("id")); Danbooru.Note.Body.show($note_box_inner.data("id"));
if (Danbooru.Note.editing) {
var $this = $(this);
$this.resizable("enable");
$this.draggable("enable");
}
} else if (e.type === "mouseout") { } else if (e.type === "mouseout") {
Danbooru.Note.Body.hide($note_box_inner.data("id")); Danbooru.Note.Body.hide($note_box_inner.data("id"));
if (Danbooru.Note.editing) {
var $this = $(this);
$this.resizable("disable");
$this.draggable("disable");
}
} }
e.stopPropagation(); e.stopPropagation();
@@ -89,25 +99,36 @@ Danbooru.Note = {
scale: function($note_box) { scale: function($note_box) {
var $image = $("#image"); var $image = $("#image");
var ratio = $image.width() / parseFloat($("#image").data("original-width")); var ratio = $image.width() / parseFloat($image.data("original-width"));
var $note = $("#notes > article[data-id=" + $note_box.data("id") + "]"); var MIN_SIZE = 5;
$note_box.css({ $note_box.css({
top: Math.ceil(parseFloat($note.data("y")) * ratio), top: Math.ceil(parseFloat($note_box.data("y")) * ratio),
left: Math.ceil(parseFloat($note.data("x")) * ratio), left: Math.ceil(parseFloat($note_box.data("x")) * ratio),
width: Math.ceil(parseFloat($note.data("width")) * ratio), width: Math.max(MIN_SIZE, Math.ceil(parseFloat($note_box.data("width")) * ratio)),
height: Math.ceil(parseFloat($note.data("height")) * ratio) height: Math.max(MIN_SIZE, Math.ceil(parseFloat($note_box.data("height")) * ratio))
}); });
Danbooru.Note.Box.resize_inner_border($note_box); Danbooru.Note.Box.resize_inner_border($note_box);
}, },
scale_all: function() { scale_all: function() {
var container = document.getElementById('note-container');
// Hide notes while rescaling, to prevent unnecessary reflowing
var was_visible = container.style.display != 'none';
if (was_visible) container.style.display = 'none';
$(".note-box").each(function(i, v) { $(".note-box").each(function(i, v) {
Danbooru.Note.Box.scale($(v)); Danbooru.Note.Box.scale($(v));
}); });
if (was_visible) container.style.display = 'block';
}, },
toggle_all: function() { toggle_all: function() {
$(".note-box").toggle(); // Ignore the click event when adding a note
if ((new Date).getTime() < Danbooru.Note.ignore_click_until) {
return;
}
var is_hidden = document.getElementById('note-container').style.display == 'none';
// Why does toggle() not work here?
$("#note-container").toggle(is_hidden);
} }
}, },
@@ -151,13 +172,13 @@ Danbooru.Note = {
}, },
show: function(id) { show: function(id) {
if (Danbooru.Note.editing) {
return;
}
Danbooru.Note.Body.hide_all(); Danbooru.Note.Body.hide_all();
Danbooru.Note.clear_timeouts(); Danbooru.Note.clear_timeouts();
var $note_body = Danbooru.Note.Body.find(id); var $note_body = Danbooru.Note.Body.find(id);
if (!$note_body.data('resized')) {
Danbooru.Note.Body.resize($note_body);
$note_body.data('resized', 'true');
}
$note_body.show(); $note_body.show();
Danbooru.Note.Body.initialize($note_body); Danbooru.Note.Body.initialize($note_body);
}, },
@@ -212,7 +233,7 @@ Danbooru.Note = {
} }
} while ((hi - lo) > 4) } while ((hi - lo) > 4)
if ($note_body.height() > h) { if ($note_body.height() > h) {
$note_body.css("minWidth", hi); $note_body.css("min-width", hi);
} }
} }
}, },
@@ -281,11 +302,12 @@ Danbooru.Note = {
$dialog.append($textarea); $dialog.append($textarea);
$dialog.data("id", $note_body.data("id")); $dialog.data("id", $note_body.data("id"));
$dialog.dialog({ $dialog.dialog({
width: 350, width: 360,
dialogClass: "note-edit-dialog", dialogClass: "note-edit-dialog",
title: "Edit note", title: "Edit note",
buttons: { buttons: {
"Save": Danbooru.Note.Edit.save, "Save": Danbooru.Note.Edit.save,
"Preview": Danbooru.Note.Edit.preview,
"Cancel": Danbooru.Note.Edit.cancel, "Cancel": Danbooru.Note.Edit.cancel,
"Delete": Danbooru.Note.Edit.delete, "Delete": Danbooru.Note.Edit.delete,
"History": Danbooru.Note.Edit.history "History": Danbooru.Note.Edit.history
@@ -296,7 +318,7 @@ Danbooru.Note = {
$(".note-box").resizable("enable"); $(".note-box").resizable("enable");
$(".note-box").draggable("enable"); $(".note-box").draggable("enable");
}); });
// Danbooru.Note.editing = true; Danbooru.Note.editing = true;
}, },
parameterize_note: function($note_box, $note_body) { parameterize_note: function($note_box, $note_body) {
@@ -344,7 +366,11 @@ Danbooru.Note = {
var $note_box = Danbooru.Note.Box.find(id); var $note_box = Danbooru.Note.Box.find(id);
var text = $textarea.val(); var text = $textarea.val();
$note_body.data("original-body", text); $note_body.data("original-body", text);
Danbooru.Note.Body.set_text($note_body, text); Danbooru.Note.Body.set_text($note_body, "Loading...");
$.get("/note_previews.json", {body: text}).success(function(data) {
Danbooru.Note.Body.set_text($note_body, data.body);
$note_body.show();
});
$this.dialog("close"); $this.dialog("close");
if (id.match(/\d/)) { if (id.match(/\d/)) {
@@ -364,6 +390,19 @@ Danbooru.Note = {
} }
}, },
preview: function() {
var $this = $(this);
var $textarea = $this.find("textarea");
var id = $this.data("id");
var $note_body = Danbooru.Note.Body.find(id);
var text = $textarea.val();
Danbooru.Note.Body.set_text($note_body, "Loading...");
$.get("/note_previews.json", {body: text}).success(function(data) {
Danbooru.Note.Body.set_text($note_body, data.body);
$note_body.show();
});
},
cancel: function() { cancel: function() {
$(this).dialog("close"); $(this).dialog("close");
}, },
@@ -377,7 +416,7 @@ Danbooru.Note = {
var id = $this.data("id"); var id = $this.data("id");
Danbooru.Note.Box.find(id).remove(); Danbooru.Note.Box.find(id).remove();
Danbooru.Note.Body.find(id).remove(); Danbooru.Note.Body.find(id).remove();
$(this).dialog("close"); $this.dialog("close");
if (id.match(/\d/)) { if (id.match(/\d/)) {
$.ajax("/notes/" + id + ".js", { $.ajax("/notes/" + id + ".js", {
@@ -408,22 +447,128 @@ Danbooru.Note = {
Danbooru.Note.TranslationMode.active = true; Danbooru.Note.TranslationMode.active = true;
$("#original-file-link").click(); $("#original-file-link").click();
$("#image").one("click", Danbooru.Note.TranslationMode.create_note); $("#image").one("mousedown", Danbooru.Note.TranslationMode.Drag.start);
Danbooru.notice('Click on the image to create a note (shortcut is <span class="key">n</span>)'); $(window).bind("mouseup", Danbooru.Note.TranslationMode.Drag.stop);
Danbooru.notice('Click or drag on the image to create a note (shortcut is <span class="key">n</span>)');
}, },
stop: function() { stop: function() {
Danbooru.Note.TranslationMode.active = false; Danbooru.Note.TranslationMode.active = false;
}, },
create_note: function(e) { create_note: function(e,dragged,x,y,w,h) {
Danbooru.Note.TranslationMode.active = false; Danbooru.Note.TranslationMode.active = false;
var offset = $("#image").offset(); var offset = $("#image").offset();
Danbooru.Note.new(e.pageX - offset.left, e.pageY - offset.top);
if (dragged) {
if (w > 9 || h > 9) { /* minimum note size: 10px */
if (w <= 9) {
w = 10;
} else if (h <= 9) {
h = 10;
}
Danbooru.Note.new(x - offset.left, y - offset.top, w, h);
}
} else {
Danbooru.Note.new(e.pageX - offset.left, e.pageY - offset.top);
}
Danbooru.Note.TranslationMode.stop(); Danbooru.Note.TranslationMode.stop();
$(".note-box").show(); $("#note-container").show();
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
// Hack to ignore clicks for some milliseconds
// The mouseup event is executed before the click event, so it's hard to do this properly
Danbooru.Note.ignore_click_until = (new Date).getTime() + 200;
},
Drag: {
dragging: false,
dragStartX: 0,
dragStartY: 0,
dragDistanceX: 0,
dragDistanceY: 0,
x: 0,
y: 0,
w: 0,
h: 0,
start: function (e) {
e.preventDefault(); /* don't drag the image */
$(window).mousemove(Danbooru.Note.TranslationMode.Drag.drag);
Danbooru.Note.TranslationMode.Drag.dragStartX = e.pageX;
Danbooru.Note.TranslationMode.Drag.dragStartY = e.pageY;
},
drag: function (e) {
Danbooru.Note.TranslationMode.Drag.dragDistanceX = e.pageX - Danbooru.Note.TranslationMode.Drag.dragStartX;
Danbooru.Note.TranslationMode.Drag.dragDistanceY = e.pageY - Danbooru.Note.TranslationMode.Drag.dragStartY;
var $image = $("#image");
var offset = $image.offset();
var limitX1 = $image.width() - Danbooru.Note.TranslationMode.Drag.dragStartX + offset.left - 1;
var limitX2 = offset.left - Danbooru.Note.TranslationMode.Drag.dragStartX;
var limitY1 = $image.height()- Danbooru.Note.TranslationMode.Drag.dragStartY + offset.top - 1;
var limitY2 = offset.top - Danbooru.Note.TranslationMode.Drag.dragStartY;
if(Danbooru.Note.TranslationMode.Drag.dragDistanceX > limitX1) {
Danbooru.Note.TranslationMode.Drag.dragDistanceX = limitX1;
} else if(Danbooru.Note.TranslationMode.Drag.dragDistanceX < limitX2) {
Danbooru.Note.TranslationMode.Drag.dragDistanceX = limitX2;
}
if(Danbooru.Note.TranslationMode.Drag.dragDistanceY > limitY1) {
Danbooru.Note.TranslationMode.Drag.dragDistanceY = limitY1;
} else if(Danbooru.Note.TranslationMode.Drag.dragDistanceY < limitY2) {
Danbooru.Note.TranslationMode.Drag.dragDistanceY = limitY2;
}
if (Math.abs(Danbooru.Note.TranslationMode.Drag.dragDistanceX) > 9 && Math.abs(Danbooru.Note.TranslationMode.Drag.dragDistanceY) > 9) {
Danbooru.Note.TranslationMode.Drag.dragging = true; /* must drag at least 10pixels (minimum note size) in both dimensions. */
}
if (Danbooru.Note.TranslationMode.Drag.dragging) {
if (Danbooru.Note.TranslationMode.Drag.dragDistanceX >= 0) {
Danbooru.Note.TranslationMode.Drag.x = Danbooru.Note.TranslationMode.Drag.dragStartX;
Danbooru.Note.TranslationMode.Drag.w = Danbooru.Note.TranslationMode.Drag.dragDistanceX;
} else {
Danbooru.Note.TranslationMode.Drag.x = Danbooru.Note.TranslationMode.Drag.dragStartX + Danbooru.Note.TranslationMode.Drag.dragDistanceX;
Danbooru.Note.TranslationMode.Drag.w = -Danbooru.Note.TranslationMode.Drag.dragDistanceX;
}
if (Danbooru.Note.TranslationMode.Drag.dragDistanceY >= 0) {
Danbooru.Note.TranslationMode.Drag.y = Danbooru.Note.TranslationMode.Drag.dragStartY;
Danbooru.Note.TranslationMode.Drag.h = Danbooru.Note.TranslationMode.Drag.dragDistanceY;
} else {
Danbooru.Note.TranslationMode.Drag.y = Danbooru.Note.TranslationMode.Drag.dragStartY + Danbooru.Note.TranslationMode.Drag.dragDistanceY;
Danbooru.Note.TranslationMode.Drag.h = -Danbooru.Note.TranslationMode.Drag.dragDistanceY;
}
$('#note-preview').css({
display: 'block',
left: (Danbooru.Note.TranslationMode.Drag.x + 1),
top: (Danbooru.Note.TranslationMode.Drag.y + 1),
width: (Danbooru.Note.TranslationMode.Drag.w - 3),
height: (Danbooru.Note.TranslationMode.Drag.h - 3)
});
}
},
stop: function (e) {
if(Danbooru.Note.TranslationMode.Drag.dragStartX === 0) {
return; /* 'stop' is bound to window, don't create note if start wasn't triggered */
}
$(window).unbind("mousemove");
if(Danbooru.Note.TranslationMode.Drag.dragging) {
$('#note-preview').css({display:'none'});
Danbooru.Note.TranslationMode.create_note(e, true, Danbooru.Note.TranslationMode.Drag.x, Danbooru.Note.TranslationMode.Drag.y, Danbooru.Note.TranslationMode.Drag.w-1, Danbooru.Note.TranslationMode.Drag.h-1);
Danbooru.Note.TranslationMode.Drag.dragging = false; /* border of the note is pixel-perfect on the preview border */
} else { /* no dragging -> create a normal note */
Danbooru.Note.TranslationMode.create_note(e);
}
$(window).unbind("mouseup", Danbooru.Note.TranslationMode.Drag.stop);
Danbooru.Note.TranslationMode.Drag.dragStartX = 0;
Danbooru.Note.TranslationMode.Drag.dragStartY = 0;
}
} }
}, },
@@ -432,38 +577,36 @@ Danbooru.Note = {
editing: false, editing: false,
timeouts: [], timeouts: [],
pending: {}, pending: {},
ignore_click_until: 0,
add: function(id, x, y, w, h, text) { add: function(container, id, x, y, w, h, text) {
var $note_box = Danbooru.Note.Box.create(id); var $note_box = Danbooru.Note.Box.create(id);
var $note_body = Danbooru.Note.Body.create(id); var $note_body = Danbooru.Note.Body.create(id);
$note_box.css({ $note_box.data('x', x);
left: x, $note_box.data('y', y);
top: y, $note_box.data('width', w);
width: w, $note_box.data('height', h);
height: h, container.appendChild($note_box[0]);
display: 'none' container.appendChild($note_body[0]);
});
$("#note-container").append($note_box);
$("#note-container").append($note_body);
$note_body.data("original-body", text); $note_body.data("original-body", text);
Danbooru.Note.Box.scale($note_box); Danbooru.Note.Box.scale($note_box);
Danbooru.Note.Body.set_text($note_body, text); Danbooru.Note.Body.display_text($note_body, text);
}, },
new: function(x, y) { new: function(x, y, w, h) {
var $note_box = Danbooru.Note.Box.create(Danbooru.Note.id); var $note_box = Danbooru.Note.Box.create(Danbooru.Note.id);
var $note_body = Danbooru.Note.Body.create(Danbooru.Note.id); var $note_body = Danbooru.Note.Body.create(Danbooru.Note.id);
$note_box.css({ $note_box.css({
top: y, top: y,
left: x left: x,
width: w,
height: h
}); });
$note_box.find(".note-box-inner-border").addClass("unsaved"); $note_box.find(".note-box-inner-border").addClass("unsaved");
$note_body.html("<em>Click to edit</em>"); $note_body.html("<em>Click to edit</em>");
$("#note-container").append($note_box); $("#note-container").append($note_box);
$("#note-container").append($note_body); $("#note-container").append($note_body);
Danbooru.Note.Body.resize($note_body);
Danbooru.Note.Box.resize_inner_border($note_box); Danbooru.Note.Box.resize_inner_border($note_box);
Danbooru.Note.id += "x"; Danbooru.Note.id += "x";
}, },
@@ -477,9 +620,11 @@ Danbooru.Note = {
}, },
load_all: function() { load_all: function() {
var fragment = document.createDocumentFragment();
$.each($("#notes article"), function(i, article) { $.each($("#notes article"), function(i, article) {
var $article = $(article); var $article = $(article);
Danbooru.Note.add( Danbooru.Note.add(
fragment,
$article.data("id"), $article.data("id"),
$article.data("x"), $article.data("x"),
$article.data("y"), $article.data("y"),
@@ -488,12 +633,7 @@ Danbooru.Note = {
$article.html() $article.html()
); );
}); });
$("#note-container").append(fragment);
$('#note-container').css('display','none');
$('.note-box').each(function(i, v) {
$(v).css('display','block')
});
$('#note-container').css('display','block');
} }
} }

View File

@@ -4,7 +4,7 @@
Danbooru.Post.pending_update_count = 0; Danbooru.Post.pending_update_count = 0;
Danbooru.Post.initialize_all = function() { Danbooru.Post.initialize_all = function() {
this.initialize_titles(); this.initialize_post_previews();
if ($("#c-posts").length) { if ($("#c-posts").length) {
if (Danbooru.meta("enable-js-navigation") === "true") { if (Danbooru.meta("enable-js-navigation") === "true") {
@@ -24,7 +24,6 @@
this.initialize_post_image_resize_links(); this.initialize_post_image_resize_links();
this.initialize_post_image_resize_to_window_link(); this.initialize_post_image_resize_to_window_link();
this.initialize_similar(); this.initialize_similar();
this.place_jlist_ads();
if (Danbooru.meta("always-resize-images") === "true") { if (Danbooru.meta("always-resize-images") === "true") {
$("#image-resize-to-window-link").click(); $("#image-resize-to-window-link").click();
@@ -92,7 +91,7 @@
Danbooru.Post.initialize_shortcuts = function() { Danbooru.Post.initialize_shortcuts = function() {
$(document).bind("keydown.q", function(e) { $(document).bind("keydown.q", function(e) {
$("#tags").trigger("focus"); $("#tags").trigger("focus").selectEnd();
e.preventDefault(); e.preventDefault();
}); });
@@ -138,10 +137,12 @@
Danbooru.Post.initialize_post_relationship_previews = function() { Danbooru.Post.initialize_post_relationship_previews = function() {
var current_post_id = $("meta[name=post-id]").attr("content"); var current_post_id = $("meta[name=post-id]").attr("content");
$("#post_" + current_post_id).css("background-color", "rgba(0,0,0,0.05)"); $("#post_" + current_post_id).addClass("current-post");
this.toggle_relationship_preview($("#has-children-relationship-preview"), $("#has-children-relationship-preview-link")); if (Danbooru.Cookie.get("show-relationship-previews") === "0") {
this.toggle_relationship_preview($("#has-parent-relationship-preview"), $("#has-parent-relationship-preview-link")); this.toggle_relationship_preview($("#has-children-relationship-preview"), $("#has-children-relationship-preview-link"));
this.toggle_relationship_preview($("#has-parent-relationship-preview"), $("#has-parent-relationship-preview-link"));
}
$("#has-children-relationship-preview-link").click(function(e) { $("#has-children-relationship-preview-link").click(function(e) {
Danbooru.Post.toggle_relationship_preview($("#has-children-relationship-preview"), $(this)); Danbooru.Post.toggle_relationship_preview($("#has-children-relationship-preview"), $(this));
@@ -158,15 +159,21 @@
preview.toggle(); preview.toggle();
if (preview.is(":visible")) { if (preview.is(":visible")) {
preview_link.html("&laquo; hide"); preview_link.html("&laquo; hide");
Danbooru.Cookie.put("show-relationship-previews", "1");
} }
else { else {
preview_link.html("show &raquo;"); preview_link.html("show &raquo;");
Danbooru.Cookie.put("show-relationship-previews", "0");
} }
} }
Danbooru.Post.initialize_favlist = function() { Danbooru.Post.initialize_favlist = function() {
$("#favlist").hide(); $("#favlist").hide();
$("#hide-favlist-link").hide(); $("#hide-favlist-link").hide();
var fav_count = $("#show-favlist-link").prev().text();
if (fav_count === "0") {
$("#show-favlist-link").hide();
}
$("#show-favlist-link").click(function(e) { $("#show-favlist-link").click(function(e) {
$("#favlist").show(); $("#favlist").show();
@@ -183,9 +190,10 @@
}); });
} }
Danbooru.Post.initialize_titles = function() { Danbooru.Post.initialize_post_previews = function() {
$(".post-preview").each(function(i, v) { $(".post-preview").each(function(i, v) {
Danbooru.Post.initialize_title_for(v); Danbooru.Post.initialize_title_for(v);
Danbooru.Post.initialize_preview_borders_for(v);
}); });
} }
@@ -195,6 +203,36 @@
$img.attr("title", $post.attr("data-tags") + " user:" + $post.attr("data-uploader") + " rating:" + $post.data("rating") + " score:" + $post.data("score")); $img.attr("title", $post.attr("data-tags") + " user:" + $post.attr("data-uploader") + " rating:" + $post.data("rating") + " score:" + $post.data("score"));
} }
Danbooru.Post.initialize_preview_borders_for = function(post) {
var $post = $(post);
var $img = $post.find("img");
var border_colors = [];
if ($post.hasClass("post-status-has-children")) {
border_colors.push("#0F0");
}
if ($post.hasClass("post-status-has-parent")) {
border_colors.push("#CC0");
}
if ($post.hasClass("post-status-deleted")) {
border_colors.push("#000");
} else if ($post.hasClass("post-status-pending")) {
border_colors.push("#00F");
} else if ($post.hasClass("post-status-flagged")) {
border_colors.push("#F00");
}
if (border_colors.length > 1) {
$img.css("border", "2px solid");
if (border_colors.length === 2) {
$img.css("border-color", border_colors[0] + " " + border_colors[1] + " " + border_colors[1] + " " + border_colors[0]);
} else if (border_colors.length === 3) {
$img.css("border-color", border_colors[0] + " " + border_colors[2] + " " + border_colors[2] + " " + border_colors[1]);
}
}
}
Danbooru.Post.initialize_post_image_resize_links = function() { Danbooru.Post.initialize_post_image_resize_links = function() {
$("#image-resize-link").click(function(e) { $("#image-resize-link").click(function(e) {
var $link = $(e.target); var $link = $(e.target);
@@ -204,7 +242,6 @@
$image.height($image.data("original-height")); $image.height($image.data("original-height"));
Danbooru.Note.Box.scale_all(); Danbooru.Note.Box.scale_all();
$("#image-resize-notice").hide(); $("#image-resize-notice").hide();
Danbooru.Post.place_jlist_ads();
$image.data("scale_factor", 1); $image.data("scale_factor", 1);
e.preventDefault(); e.preventDefault();
}); });
@@ -233,7 +270,6 @@
} }
Danbooru.Note.Box.scale_all(); Danbooru.Note.Box.scale_all();
Danbooru.Post.place_jlist_ads()
e.preventDefault(); e.preventDefault();
}); });
} }
@@ -355,35 +391,6 @@
} }
}); });
} }
Danbooru.Post.place_jlist_ads = function() {
var jlist = $("#jlist-rss-ads-for-show");
if (jlist.length) {
var image = $("#image");
if (image.length) {
var x = image.offset().left + image.width() + 50;
var y = image.offset().top;
if (x > $(window).width()) {
jlist.css({
position: "absolute",
width: "108px",
left: x + "px",
top: y + "px"
});
} else {
jlist.css({
position: "absolute",
width: "108px",
right: "10px",
top: y + "px"
});
}
} else {
jlist.hide();
}
}
}
})(); })();
$(document).ready(function() { $(document).ready(function() {

View File

@@ -47,10 +47,10 @@
// 5. abc| def -> abc // 5. abc| def -> abc
// 6. ab|c def -> abc // 6. ab|c def -> abc
// 7. |abc def -> abc // 7. |abc def -> abc
// 8. | abc def -> abc -- not supported by this code but a pretty rare case // 8. | abc def -> abc
var $field = $("#upload_tag_string,#post_tag_string"); var $field = $("#upload_tag_string,#post_tag_string");
var string = $field.val().trim(); var string = $field.val();
var n = string.length; var n = string.length;
var a = $field.get(0).selectionStart; var a = $field.get(0).selectionStart;
var b = $field.get(0).selectionStart; var b = $field.get(0).selectionStart;
@@ -59,6 +59,11 @@
// 4 is the only case where we need to scan forward. in all other cases we // 4 is the only case where we need to scan forward. in all other cases we
// can drag a backwards, and then drag b forwards. // can drag a backwards, and then drag b forwards.
while ((b < n) && (!/\s/.test(string[b]))) {
b++;
}
} else if (string.search(/\S/) > b) { // case 8
b = string.search(/\S/);
while ((b < n) && (!/\s/.test(string[b]))) { while ((b < n) && (!/\s/.test(string[b]))) {
b++; b++;
} }
@@ -119,6 +124,8 @@
$.each(Danbooru.RelatedTag.recent_artists[0].urls, function(i, url) { $.each(Danbooru.RelatedTag.recent_artists[0].urls, function(i, url) {
tags.push([" " + url.url, 0]); tags.push([" " + url.url, 0]);
}); });
} else if (Danbooru.RelatedTag.recent_artists.length >= 10) {
tags.push([" none", 0]);
} else { } else {
$.each(Danbooru.RelatedTag.recent_artists, function(i, artist) { $.each(Danbooru.RelatedTag.recent_artists, function(i, artist) {
tags.push([artist.name, 1]); tags.push([artist.name, 1]);
@@ -155,6 +162,16 @@
return ""; return "";
} }
query = query.replace(/_/g, " ");
var header = $("<em/>");
var match = query.match(/^wiki:(.+)/);
if (match) {
header.html($("<a/>").attr("href", "/wiki_pages?title=" + encodeURIComponent(match[1])).attr("target", "_blank").text(query));
} else {
header.text(query);
}
var current = $("#upload_tag_string,#post_tag_string").val().match(/\S+/g) || []; var current = $("#upload_tag_string,#post_tag_string").val().match(/\S+/g) || [];
var $div = $("<div/>"); var $div = $("<div/>");
$div.addClass("tag-column") $div.addClass("tag-column")
@@ -164,16 +181,14 @@
var $ul = $("<ul/>"); var $ul = $("<ul/>");
$ul.append( $ul.append(
$("<li/>").append( $("<li/>").append(
$("<em/>").html( header
query.replace(/_/g, " ")
)
) )
); );
$.each(related_tags, function(i, tag) { $.each(related_tags, function(i, tag) {
if (tag[0][0] !== " ") { if (tag[0][0] !== " ") {
var $link = $("<a/>"); var $link = $("<a/>");
$link.html(tag[0].replace(/_/g, " ")); $link.text(tag[0].replace(/_/g, " "));
$link.addClass("tag-type-" + tag[1]); $link.addClass("tag-type-" + tag[1]);
$link.attr("href", "/posts?tags=" + encodeURIComponent(tag[0])); $link.attr("href", "/posts?tags=" + encodeURIComponent(tag[0]));
$link.click(Danbooru.RelatedTag.toggle_tag); $link.click(Danbooru.RelatedTag.toggle_tag);
@@ -184,7 +199,7 @@
$("<li/>").append($link) $("<li/>").append($link)
); );
} else { } else {
$ul.append($("<li/>").html(tag[0])); $ul.append($("<li/>").text(tag[0]));
} }
}); });
@@ -210,6 +225,8 @@
if (Danbooru.RelatedTag.recent_artist && $("#artist-tags-container").css("display") === "block") { if (Danbooru.RelatedTag.recent_artist && $("#artist-tags-container").css("display") === "block") {
Danbooru.RelatedTag.process_artist(Danbooru.RelatedTag.recent_artist); Danbooru.RelatedTag.process_artist(Danbooru.RelatedTag.recent_artist);
} }
$field.focus();
e.preventDefault(); e.preventDefault();
} }

View File

@@ -22,11 +22,11 @@
} }
Danbooru.notice = function(msg) { Danbooru.notice = function(msg) {
$('#notice').html(msg).addClass("ui-state-highlight").removeClass("ui-state-error").fadeIn("fast"); $('#notice').addClass("ui-state-highlight").removeClass("ui-state-error").fadeIn("fast").children("span").html(msg);
} }
Danbooru.error = function(msg) { Danbooru.error = function(msg) {
$('#notice').html(msg).removeClass("ui-state-highlight").addClass("ui-state-error").fadeIn("fast"); $('#notice').removeClass("ui-state-highlight").addClass("ui-state-error").fadeIn("fast").children("span").html(msg);
Danbooru.scroll_to($("#notice")); Danbooru.scroll_to($("#notice"));
} }

View File

@@ -19,7 +19,7 @@ abbr[title=required] {
blockquote { blockquote {
margin: 0 0 1em 0; margin: 0 0 1em 0;
padding: 1em; padding: 1em 1em 0.2em;
border: 1px solid #666; border: 1px solid #666;
background: #EEE; background: #EEE;
} }

View File

@@ -12,3 +12,7 @@ div#notice {
margin: 1em 0; margin: 1em 0;
padding: 1em; padding: 1em;
} }
a#close-notice-link {
float: right;
}

View File

@@ -19,8 +19,16 @@ div#c-artists {
div#a-edit, div#a-new { div#a-edit, div#a-new {
textarea { textarea {
height: 5em; height: 10em;
&#artist_other_names_comma {
height: 3em;
}
} }
.hint {
display: block;
}
} }
div.recent-posts { div.recent-posts {

View File

@@ -1,7 +1,6 @@
@import "../common/000_vars.css.scss"; @import "../common/000_vars.css.scss";
div.comments-for-post { div.comments-for-post {
float: left;
div.notices { div.notices {
margin: 1em 0; margin: 1em 0;
} }
@@ -15,13 +14,13 @@ div.comments-for-post {
div.list-of-comments { div.list-of-comments {
article.comment { article.comment {
margin-bottom: 2em; margin-bottom: 2em;
word-wrap: break-word;
div.author { div.author {
width: 12em; width: 12em;
float: left; float: left;
overflow: hidden; overflow: hidden;
margin-right: 2em; margin-right: 1em;
word-wrap: break-word;
h1 { h1 {
display: block; display: block;
@@ -30,8 +29,8 @@ div.comments-for-post {
} }
div.content { div.content {
width: 40em; margin-left: 13em;
float: left; min-width: 17em;
menu { menu {
li { li {
@@ -61,6 +60,12 @@ div.comments-for-post {
} }
} }
div#c-posts {
div.comments-for-post {
float: left;
}
}
div#c-comments { div#c-comments {
div#a-index, div#a-show { div#a-index, div#a-show {
div.header { div.header {
@@ -96,8 +101,21 @@ div#c-comments {
margin-bottom: 4em; margin-bottom: 4em;
div.comments-for-post { div.comments-for-post {
float: left; margin-left: 184px;
width: 55em; min-width: 30em;
div.list-of-comments {
float: left;
width: 100%;
}
}
}
div.comments-for-post {
div.post {
article.comment {
margin-left: 184px;
}
} }
} }

View File

@@ -7,12 +7,12 @@ div.list-of-forum-posts {
article { article {
margin-bottom: 3em; margin-bottom: 3em;
word-wrap: break-word;
div.author { div.author {
width: 12em; width: 12em;
float: left; float: left;
margin-right: 2em; margin-right: 2em;
word-wrap: break-word;
} }
div.content { div.content {
@@ -53,4 +53,8 @@ div#c-forum-topics {
span.locked-topic { span.locked-topic {
color: #666; color: #666;
} }
tr.forum-topic-row td:last-child {
white-space: nowrap;
}
} }

View File

@@ -0,0 +1,7 @@
div#c-news-updates {
div#a-edit, div#a-new {
.hint {
display: block;
}
}
}

View File

@@ -57,6 +57,14 @@ div#note-container {
} }
} }
div#note-preview {
position: absolute;
border: 1px solid red;
opacity: 0.6;
display: none;
background: white;
}
div.note-edit-dialog { div.note-edit-dialog {
font-size: 0.8em; font-size: 0.8em;
} }

View File

@@ -32,9 +32,10 @@ div#c-pools {
color: #AAA; color: #AAA;
} }
#content { div#a-show {
margin-left: 0; div#description {
padding-left: 0; margin-bottom: 1em;
}
} }
} }

View File

@@ -46,6 +46,23 @@ a.blacklisted-active {
border: 2px solid #F00; border: 2px solid #F00;
} }
.post-preview.current-post {
background-color: rgba(0,0,0,0.1);
}
#has-parent-relationship-preview, #has-children-relationship-preview {
overflow-x: auto;
white-space: nowrap;
article.post-preview {
float: none;
width: auto;
border: none;
margin: 0px;
padding: 5px 5px 10px;
}
}
.category-1 a, a.tag-type-1 { .category-1 a, a.tag-type-1 {
color: #A00; color: #A00;
} }
@@ -134,8 +151,8 @@ body.mode-tag-script {
div#c-posts { div#c-posts {
div.notice { div.notice {
font-size: 0.8em; font-size: 0.8em;
padding: 1em; padding: 0.5em;
margin-bottom: 1em; margin-bottom: 0.5em;
overflow: hidden; overflow: hidden;
ul { ul {
@@ -153,8 +170,8 @@ div#c-posts {
} }
div.nav-notice { div.nav-notice {
padding: 1em; padding: 0.5em;
margin-bottom: 1em; margin: 1em 0;
background: #EEE; background: #EEE;
border: 1px solid #AAA; border: 1px solid #AAA;
position: relative; position: relative;
@@ -247,11 +264,6 @@ div#c-posts {
word-wrap: break-word; word-wrap: break-word;
} }
#nav-links {
margin: 1em 0;
padding: 1em 0.5em;
}
#content.with-ads { #content.with-ads {
margin-right: 7em; margin-right: 7em;
} }
@@ -261,21 +273,37 @@ div#c-posts {
word-wrap: break-word; word-wrap: break-word;
} }
#search-seq-nav + #pool-nav {
margin-top: 0.5em;
}
#pool-nav, #search-seq-nav, #nav-help { #pool-nav, #search-seq-nav, #nav-help {
li { li {
position: relative; position: relative;
text-align: center; text-align: center;
padding: 0px 4.5em; padding: 0px 5.5em;
.prev { .prev {
position: absolute; position: absolute;
left: 1em; left: 2em;
top: 0px; top: 0px;
} }
.next { .next {
position: absolute; position: absolute;
right: 1em; right: 2em;
top: 0px;
}
.first {
position: absolute;
left: 0.5em;
top: 0px;
}
.last {
position: absolute;
right: 0.5em;
top: 0px; top: 0px;
} }

View File

@@ -6,7 +6,7 @@ module Admin
end end
def create def create
@importer = AliasAndImplicationImporter.new(params[:batch][:text], params[:batch][:forum_id]) @importer = AliasAndImplicationImporter.new(params[:batch][:text], params[:batch][:forum_id], params[:batch][:rename_aliased_pages])
@importer.process! @importer.process!
flash[:notice] = "Import queued" flash[:notice] = "Import queued"
redirect_to new_admin_alias_and_implication_import_path redirect_to new_admin_alias_and_implication_import_path

View File

@@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base
before_filter :set_current_user before_filter :set_current_user
after_filter :reset_current_user after_filter :reset_current_user
before_filter :set_title before_filter :set_title
before_filter :normalize_search
before_filter :set_started_at_session before_filter :set_started_at_session
before_filter :api_check before_filter :api_check
layout "default" layout "default"
@@ -100,4 +101,8 @@ protected
def set_title def set_title
@page_title = Danbooru.config.app_name + "/#{params[:controller]}" @page_title = Danbooru.config.app_name + "/#{params[:controller]}"
end end
def normalize_search
params[:search] ||= {}
end
end end

View File

@@ -14,6 +14,7 @@ class DmailsController < ApplicationController
end end
def index def index
cookies[:dmail_folder] = params[:folder]
@search = Dmail.visible.search(params[:search]) @search = Dmail.visible.search(params[:search])
@dmails = @search.order("dmails.created_at desc").paginate(params[:page]) @dmails = @search.order("dmails.created_at desc").paginate(params[:page])
respond_with(@dmails) do |format| respond_with(@dmails) do |format|

View File

@@ -1,15 +1,18 @@
class FavoritesController < ApplicationController class FavoritesController < ApplicationController
before_filter :member_only before_filter :member_only
respond_to :html, :xml, :json
def index def index
if params[:tags] if params[:tags]
redirect_to(posts_path(:tags => params[:tags])) redirect_to(posts_path(:tags => params[:tags]))
elsif request.format == Mime::JS
list_favorited_users
elsif params[:user_id]
@favorite_set = PostSets::Favorite.new(User.find(params[:user_id]), params[:page], params)
else else
@favorite_set = PostSets::Favorite.new(CurrentUser.user, params[:page], params) user_id = params[:user_id] || CurrentUser.user.id
@favorite_set = PostSets::Favorite.new(user_id, params[:page], params)
respond_with(@favorite_set.posts) do |format|
format.xml do
render :xml => @favorite_set.posts.to_xml(:root => "posts")
end
end
end end
end end
@@ -26,9 +29,4 @@ class FavoritesController < ApplicationController
@post = Post.find(params[:id]) @post = Post.find(params[:id])
@post.remove_favorite!(CurrentUser.user) @post.remove_favorite!(CurrentUser.user)
end end
def list_favorited_users
@post = Post.find(params[:post_id])
render :action => "list_favorited_users"
end
end end

View File

@@ -56,7 +56,7 @@ class ForumPostsController < ApplicationController
def destroy def destroy
@forum_post = ForumPost.find(params[:id]) @forum_post = ForumPost.find(params[:id])
raise User::PrivilegeError unless @forum_post.editable_by?(CurrentUser.user) raise User::PrivilegeError unless @forum_post.editable_by?(CurrentUser.user)
@forum_post.update_attribute(:is_deleted, true) @forum_post.update_column(:is_deleted, true)
respond_with(@forum_post) respond_with(@forum_post)
end end

View File

@@ -0,0 +1,12 @@
class NotePreviewsController < ApplicationController
respond_to :json
def show
@body = DText.sanitize(params[:body].to_s)
respond_with(@body) do |format|
format.json do
render :json => {:body => @body}.to_json
end
end
end
end

View File

@@ -68,6 +68,8 @@ class PoolsController < ApplicationController
@pool = Pool.find(params[:id]) @pool = Pool.find(params[:id])
@version = PoolVersion.find(params[:version_id]) @version = PoolVersion.find(params[:version_id])
@pool.revert_to!(@version) @pool.revert_to!(@version)
respond_with(@pool, :notice => "Pool reverted") respond_with(@pool) do |format|
format.js
end
end end
end end

View File

@@ -13,7 +13,9 @@ class PostsController < ApplicationController
respond_with(@posts) do |format| respond_with(@posts) do |format|
format.atom format.atom
format.xml do format.xml do
render :xml => @posts.to_xml(:root => "posts") render :xml => @posts.to_xml(:root => "posts") {|builder|
builder.tag!(:total_count, @posts.total_count)
}
end end
end end
end end
@@ -22,13 +24,8 @@ class PostsController < ApplicationController
@post = Post.find(params[:id]) @post = Post.find(params[:id])
@post_flag = PostFlag.new(:post_id => @post.id) @post_flag = PostFlag.new(:post_id => @post.id)
@post_appeal = PostAppeal.new(:post_id => @post.id) @post_appeal = PostAppeal.new(:post_id => @post.id)
@parent_post_set = PostSets::PostRelationship.new(@post.parent_id, :include_deleted => @post.is_deleted?)
@children_post_set = PostSets::Post.new("parent:#{@post.id} -id:#{@post.id}", 1, 200) @children_post_set = PostSets::PostRelationship.new(@post.id, :include_deleted => @post.is_deleted?)
@children_post_set.posts.reverse!
@parent_post_set = PostSets::Post.new("id:#{@post.parent_id} status:any")
@siblings_post_set = PostSets::Post.new("parent:#{@post.parent_id} -id:#{@post.parent_id}", 1, 200)
@siblings_post_set.posts.reverse!
respond_with(@post) respond_with(@post)
end end

View File

@@ -25,7 +25,12 @@ class TagImplicationsController < ApplicationController
def destroy def destroy
@tag_implication = TagImplication.find(params[:id]) @tag_implication = TagImplication.find(params[:id])
@tag_implication.destroy @tag_implication.destroy
respond_with(@tag_implication) respond_with(@tag_implication) do |format|
format.html do
flash[:notice] = "Tag implication was deleted"
redirect_to(tag_implications_path)
end
end
end end
def approve def approve

View File

@@ -15,10 +15,15 @@ class UsersController < ApplicationController
end end
def index def index
@users = User.search(params[:search]).order("users.id desc").paginate(params[:page], :search_count => params[:search]) if params[:name].present?
respond_with(@users) do |format| @user = User.find_by_name(params[:name])
format.xml do redirect_to user_path(@user)
render :xml => @users.to_xml(:root => "users") else
@users = User.search(params[:search]).order("users.id desc").paginate(params[:page], :search_count => params[:search])
respond_with(@users) do |format|
format.xml do
render :xml => @users.to_xml(:root => "users")
end
end end
end end
end end

View File

@@ -70,7 +70,8 @@ class WikiPagesController < ApplicationController
if @wiki_page if @wiki_page
redirect_to wiki_page_path(@wiki_page) redirect_to wiki_page_path(@wiki_page)
else else
redirect_to new_wiki_page_path(:wiki_page => {:title => params[:title]}) @wiki_page = WikiPage.new(:title => params[:title])
respond_with(@wiki_page)
end end
end end

View File

@@ -5,7 +5,7 @@ module ArtistsHelper
if artist if artist
link_to(artist.name, artist_path(artist)) link_to(artist.name, artist_path(artist))
else else
link_to(name, new_artist_path(:name => name)) + " " + content_tag("span", "*", :class => "new-artist") link_to(name, new_artist_path(:name => name)) + " " + content_tag("span", "*", :class => "new-artist", :title => "No artist with this name currently exists.")
end end
end end

View File

@@ -1,2 +1,12 @@
module DmailsHelper module DmailsHelper
def dmails_current_folder_path
case cookies[:dmail_folder]
when "sent"
dmails_path(:search => {:owner_id => CurrentUser.id, :from_id => CurrentUser.id}, :folder => "sent")
when "all"
dmails_path(:search => {:owner_id => CurrentUser.id}, :folder => "all")
else
dmails_path(:search => {:owner_id => CurrentUser.id, :to_id => CurrentUser.id}, :folder => "received")
end
end
end end

View File

@@ -41,16 +41,21 @@ module PostsHelper
end end
end end
def has_parent_message(post, parent_post_set, siblings_post_set) def post_favlist(post)
post.favorited_users.reverse_each.map{|user| link_to_user(user)}.join(", ").html_safe
end
def has_parent_message(post, parent_post_set)
html = "" html = ""
html << "This post belongs to a " html << "This post belongs to a "
html << link_to("parent", post_path(post.parent_id)) html << link_to("parent", post_path(post.parent_id))
html << " (deleted)" if parent_post_set.posts.first.is_deleted? html << " (deleted)" if parent_post_set.parent.first.is_deleted?
if siblings_post_set.posts.count > 1 sibling_count = parent_post_set.children.count - 1
if sibling_count > 0
html << " and has " html << " and has "
text = siblings_post_set.posts.count > 2 ? "#{siblings_post_set.posts.count - 1} siblings" : "a sibling" text = sibling_count == 1 ? "a sibling" : "#{sibling_count} siblings"
html << link_to(text, posts_path(:tags => "parent:#{post.parent_id}")) html << link_to(text, posts_path(:tags => "parent:#{post.parent_id}"))
end end
@@ -65,7 +70,7 @@ module PostsHelper
html = "" html = ""
html << "This post has " html << "This post has "
text = children_post_set.posts.count == 1 ? "a child" : "#{children_post_set.posts.count} children" text = children_post_set.children.count == 1 ? "a child" : "#{children_post_set.children.count} children"
html << link_to(text, posts_path(:tags => "parent:#{post.id}")) html << link_to(text, posts_path(:tags => "parent:#{post.id}"))
html << " (#{link_to("learn more", wiki_pages_path(:title => "help:post_relationships"))}) " html << " (#{link_to("learn more", wiki_pages_path(:title => "help:post_relationships"))}) "

View File

@@ -1,2 +1,49 @@
module WikiPagesHelper module WikiPagesHelper
def wiki_page_alias_and_implication_list(wiki_page)
antecedent_alias = wiki_page.presenter.antecedent_tag_alias
consequent_aliases = wiki_page.presenter.consequent_tag_aliases
antecedent_implications = wiki_page.presenter.antecedent_tag_implications
consequent_implications = wiki_page.presenter.consequent_tag_implications
html = ""
if antecedent_alias
html << "<p class='hint'>This tag has been aliased to "
html << link_to(antecedent_alias.consequent_name, show_or_new_wiki_pages_path(:title => antecedent_alias.consequent_name))
html << ".</p>"
end
if consequent_aliases.any?
html << "<p class='hint'>The following tags are aliased to this tag: "
html << raw(consequent_aliases.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", "))
html << ".</p>"
end
if antecedent_implications.any?
html << "<p class='hint'>This tag implicates "
html << raw(antecedent_implications.map {|x| link_to(x.consequent_name, show_or_new_wiki_pages_path(:title => x.consequent_name))}.join(", "))
html << ".</p>"
end
if consequent_implications.any?
html << "<p class='hint'>The following tags implicate this tag: "
html << raw(consequent_implications.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", "))
html << ".</p>"
end
html.html_safe
end
def wiki_page_post_previews(wiki_page)
html = '<div id="wiki-page-posts">'
if Post.fast_count(wiki_page.title) > 0
html << "<h2>Posts</h2>"
html << wiki_page.post_set.presenter.post_previews_html(self)
end
html << "</div>"
html.html_safe
end
end end

View File

@@ -1,9 +1,10 @@
class AliasAndImplicationImporter class AliasAndImplicationImporter
attr_accessor :text, :commands, :forum_id attr_accessor :text, :commands, :forum_id, :rename_aliased_pages
def initialize(text, forum_id) def initialize(text, forum_id, rename_aliased_pages = "0")
@forum_id = forum_id @forum_id = forum_id
@text = text @text = text
@rename_aliased_pages = rename_aliased_pages
end end
def process! def process!
@@ -11,6 +12,10 @@ class AliasAndImplicationImporter
parse(tokens) parse(tokens)
end end
def rename_aliased_pages?
@rename_aliased_pages == "1"
end
private private
def tokenize(text) def tokenize(text)
@@ -40,6 +45,7 @@ private
case token[0] case token[0]
when :create_alias when :create_alias
tag_alias = TagAlias.create(:forum_topic_id => forum_id, :status => "pending", :antecedent_name => token[1], :consequent_name => token[2]) tag_alias = TagAlias.create(:forum_topic_id => forum_id, :status => "pending", :antecedent_name => token[1], :consequent_name => token[2])
tag_alias.rename_wiki_and_artist if rename_aliased_pages?
tag_alias.delay(:queue => "default").process! tag_alias.delay(:queue => "default").process!
when :create_implication when :create_implication

View File

@@ -5,7 +5,7 @@ module Moderator
def initialize(min_date, max_level) def initialize(min_date, max_level)
@min_date = min_date.present? ? min_date.to_date : 1.week.ago @min_date = min_date.present? ? min_date.to_date : 1.week.ago
@max_level = max_level.present? ? User::Levels::MEMBER : max_level.to_i @max_level = max_level.present? ? max_level.to_i : User::Levels::MEMBER
end end
def artists def artists

View File

@@ -170,6 +170,20 @@ class PostQueryBuilder
end end
end end
if q[:source_neg]
if q[:source_neg] == "none%"
relation = relation.where("(posts.source != '' AND posts.source IS NOT NULL)")
elsif q[:source_neg] == "http%"
relation = relation.where("(posts.source not like ?)", "http%")
elsif q[:source_neg] =~ /^%\.?pixiv(?:\.net(?:\/img)?)?(?:%\/|(?=%$))(.+)$/
relation = relation.where("SourcePattern(posts.source) NOT LIKE ? ESCAPE E'\\\\'", "pixiv/" + $1)
has_constraints!
else
relation = relation.where("SourcePattern(posts.source) NOT LIKE SourcePattern(?) ESCAPE E'\\\\'", q[:source_neg])
has_constraints!
end
end
if q[:subscriptions] if q[:subscriptions]
relation = add_tag_subscription_relation(q[:subscriptions], relation) relation = add_tag_subscription_relation(q[:subscriptions], relation)
has_constraints! has_constraints!

View File

@@ -6,6 +6,10 @@ module PostSets
@params = params @params = params
@user = ::User.find(user_id) @user = ::User.find(user_id)
@favorites = ::Favorite.for_user(user.id).paginate(page, :limit => limit).order("favorites.id desc") @favorites = ::Favorite.for_user(user.id).paginate(page, :limit => limit).order("favorites.id desc")
if CurrentUser.user.hide_deleted_posts?
@favorites = @favorites.where("is_deleted = false")
end
end end
def limit def limit

View File

@@ -0,0 +1,24 @@
module PostSets
class PostRelationship < PostSets::Post
attr_reader :parent, :children
def initialize(parent_id, options = {})
@parent = ::Post.where("id = ?", parent_id)
@children = ::Post.where("parent_id = ?", parent_id).order("id ASC")
if options[:include_deleted]
super("parent:#{parent_id} status:any")
else
@children = @children.where("is_deleted = ?", false)
super("parent:#{parent_id}")
end
end
def posts
@parent + @children
end
def presenter
::PostSetPresenters::Post.new(self)
end
end
end

View File

@@ -2,7 +2,7 @@ module PostSets
class SearchError < Exception class SearchError < Exception
end end
class WikiPage < Post class WikiPage < PostSets::Post
def presenter def presenter
@presenter ||= ::PostSetPresenters::WikiPage.new(self) @presenter ||= ::PostSetPresenters::WikiPage.new(self)
end end

View File

@@ -74,7 +74,7 @@ private
end end
def ban_expired? def ban_expired?
CurrentUser.user.is_banned? && CurrentUser.user.ban && CurrentUser.user.ban.expired? CurrentUser.user.is_banned? && CurrentUser.user.recent_ban && CurrentUser.user.recent_ban.expired?
end end
def cookie_password_hash_valid? def cookie_password_hash_valid?

View File

@@ -4,7 +4,7 @@ require 'mail'
class UploadErrorChecker class UploadErrorChecker
def check! def check!
uploads = Upload.where("status like 'error%' and created_at >= ?", 1.hour.ago).all uploads = Upload.where("status like 'error%' and status not like 'error: RuntimeError - duplicate%' and created_at >= ?", 1.hour.ago).all
if uploads.size > 5 if uploads.size > 5
mail = Mail.new do mail = Mail.new do
from "webmaster@danbooru.donmai.us" from "webmaster@danbooru.donmai.us"

View File

@@ -28,7 +28,7 @@ class Artist < ActiveRecord::Base
u = u.to_escaped_for_sql_like.gsub(/\*/, '%') + '%' u = u.to_escaped_for_sql_like.gsub(/\*/, '%') + '%'
artists += Artist.joins(:urls).where(["artists.is_active = TRUE AND artist_urls.normalized_url LIKE ? ESCAPE E'\\\\'", u]).limit(10).order("artists.name").all artists += Artist.joins(:urls).where(["artists.is_active = TRUE AND artist_urls.normalized_url LIKE ? ESCAPE E'\\\\'", u]).limit(10).order("artists.name").all
url = File.dirname(url) + "/" url = File.dirname(url) + "/"
break if url =~ /pixiv\.net\/$/ break if url =~ /pixiv\.net\/(?:img\/)?$/
end end
artists.uniq_by {|x| x.name}.slice(0, 20) artists.uniq_by {|x| x.name}.slice(0, 20)

View File

@@ -12,24 +12,24 @@ class Favorite < ActiveRecord::Base
end end
def self.add(post, user) def self.add(post, user)
return if Favorite.for_user(user.id).exists?(:user_id => user.id, :post_id => post.id) return if Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post.id).exists?
Favorite.create(:user_id => user.id, :post_id => post.id) Favorite.create(:user_id => user.id, :post_id => post.id)
Post.update_all("fav_count = fav_count + 1", "id = #{post.id}") Post.update_all("fav_count = fav_count + 1", {:id => post.id})
Post.update_all("score = score + 1", "id = #{post.id}") if user.is_gold? Post.update_all("score = score + 1", {:id => post.id}) if user.is_gold?
post.append_user_to_fav_string(user.id) post.append_user_to_fav_string(user.id)
user.add_favorite!(post) User.update_all("favorite_count = favorite_count + 1", {:id => user.id})
user.increment!(:favorite_count) user.favorite_count += 1
post.add_favorite!(user) post.fav_count += 1
end end
def self.remove(post, user) def self.remove(post, user)
return unless Favorite.for_user(user.id).exists?(:user_id => user.id, :post_id => post.id) return unless Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post.id).exists?
Favorite.destroy_all(:user_id => user.id, :post_id => post.id) Favorite.destroy_all(:user_id => user.id, :post_id => post.id)
Post.update_all("fav_count = fav_count - 1", "id = #{post.id}") Post.update_all("fav_count = fav_count - 1", {:id => post.id})
Post.update_all("score = score - 1", "id = #{post.id}") if user.is_gold? Post.update_all("score = score - 1", {:id => post.id}) if user.is_gold?
post.delete_user_from_fav_string(user.id) post.delete_user_from_fav_string(user.id)
user.remove_favorite!(post) User.update_all("favorite_count = favorite_count - 1", {:id => user.id})
user.decrement!(:favorite_count) user.favorite_count -= 1
post.remove_favorite!(user) post.fav_count -= 1
end end
end end

View File

@@ -7,7 +7,8 @@ class ForumPost < ActiveRecord::Base
before_validation :initialize_creator, :on => :create before_validation :initialize_creator, :on => :create
before_validation :initialize_updater before_validation :initialize_updater
before_validation :initialize_is_deleted, :on => :create before_validation :initialize_is_deleted, :on => :create
after_create :update_topic_updated_at after_create :update_topic_updated_at_on_create
after_destroy :update_topic_updated_at_on_destroy
validates_presence_of :body, :creator_id validates_presence_of :body, :creator_id
validate :validate_topic_is_unlocked validate :validate_topic_is_unlocked
before_destroy :validate_topic_is_unlocked before_destroy :validate_topic_is_unlocked
@@ -87,7 +88,7 @@ class ForumPost < ActiveRecord::Base
creator_id == user.id || user.is_janitor? creator_id == user.id || user.is_janitor?
end end
def update_topic_updated_at def update_topic_updated_at_on_create
if topic if topic
topic.updater_id = CurrentUser.id topic.updater_id = CurrentUser.id
topic.response_count = topic.response_count + 1 topic.response_count = topic.response_count + 1
@@ -95,6 +96,13 @@ class ForumPost < ActiveRecord::Base
end end
end end
def update_topic_updated_at_on_destroy
max = ForumPost.where(:topic_id => topic.id).maximum(:updated_at)
if max
topic.update_column(:updated_at, max)
end
end
def initialize_creator def initialize_creator
self.creator_id = CurrentUser.id self.creator_id = CurrentUser.id
end end

View File

@@ -1,6 +1,6 @@
class NewsUpdate < ActiveRecord::Base class NewsUpdate < ActiveRecord::Base
belongs_to :creator, :class_name => "User" belongs_to :creator, :class_name => "User"
belongs_to :udpater, :class_name => "User" belongs_to :updater, :class_name => "User"
scope :recent, order("created_at desc").limit(5) scope :recent, order("created_at desc").limit(5)
before_validation :initialize_creator, :on => :create before_validation :initialize_creator, :on => :create
before_validation :initialize_updater before_validation :initialize_updater

View File

@@ -7,6 +7,8 @@ class Note < ActiveRecord::Base
before_validation :initialize_updater before_validation :initialize_updater
before_validation :blank_body before_validation :blank_body
validates_presence_of :post_id, :creator_id, :updater_id, :x, :y, :width, :height validates_presence_of :post_id, :creator_id, :updater_id, :x, :y, :width, :height
validate :post_must_exist
validate :note_within_image, :message => "must be inside the image"
has_many :versions, :class_name => "NoteVersion", :order => "note_versions.id ASC" has_many :versions, :class_name => "NoteVersion", :order => "note_versions.id ASC"
after_save :update_post after_save :update_post
after_save :create_version after_save :create_version
@@ -95,6 +97,13 @@ class Note < ActiveRecord::Base
self.updater_ip_addr = CurrentUser.ip_addr self.updater_ip_addr = CurrentUser.ip_addr
end end
def post_must_exist
if !Post.exists?(post_id)
errors.add :post, "must exist"
return false
end
end
def post_must_not_be_note_locked def post_must_not_be_note_locked
if is_locked? if is_locked?
errors.add :post, "is note locked" errors.add :post, "is note locked"
@@ -102,6 +111,14 @@ class Note < ActiveRecord::Base
end end
end end
def note_within_image
return false unless post.present?
if x < 0 || y < 0 || (x > post.image_width) || (y > post.image_height) || width < 0 || height < 0 || (x + width > post.image_width) || (y + height > post.image_height)
self.errors.add(:note, "must be inside the image")
return false
end
end
def is_locked? def is_locked?
Post.exists?(["id = ? AND is_note_locked = ?", post_id, true]) Post.exists?(["id = ? AND is_note_locked = ?", post_id, true])
end end

View File

@@ -11,6 +11,7 @@ class Pool < ActiveRecord::Base
before_validation :initialize_is_active, :on => :create before_validation :initialize_is_active, :on => :create
before_validation :initialize_creator, :on => :create before_validation :initialize_creator, :on => :create
after_save :create_version after_save :create_version
after_create :synchronize!
before_destroy :create_mod_action_for_destroy before_destroy :create_mod_action_for_destroy
attr_accessible :name, :description, :post_ids, :post_id_array, :post_count, :is_active, :as => [:member, :gold, :platinum, :contributor, :janitor, :moderator, :admin, :default] attr_accessible :name, :description, :post_ids, :post_id_array, :post_count, :is_active, :as => [:member, :gold, :platinum, :contributor, :janitor, :moderator, :admin, :default]
attr_accessible :is_deleted, :as => [:janitor, :moderator, :admin] attr_accessible :is_deleted, :as => [:janitor, :moderator, :admin]
@@ -25,9 +26,9 @@ class Pool < ActiveRecord::Base
params = {} if params.blank? params = {} if params.blank?
if params[:name_matches].present? if params[:name_matches].present?
params[:name_matches] = params[:name_matches].tr(" ", "_") name_matches = params[:name_matches].tr(" ", "_")
params[:name_matches] = "*#{params[:name_matches]}*" unless params[:name_matches] =~ /\*/ name_matches = "*#{name_matches}*" unless name_matches =~ /\*/
q = q.where("name ilike ? escape E'\\\\'", params[:name_matches].to_escaped_for_sql_like) q = q.where("name ilike ? escape E'\\\\'", name_matches.to_escaped_for_sql_like)
end end
if params[:description_matches].present? if params[:description_matches].present?

View File

@@ -3,7 +3,7 @@ class Post < ActiveRecord::Base
class DisapprovalError < Exception ; end class DisapprovalError < Exception ; end
class SearchError < Exception ; end class SearchError < Exception ; end
attr_accessor :old_tag_string, :old_parent_id, :has_constraints attr_accessor :old_tag_string, :old_parent_id, :has_constraints, :disable_versioning
after_destroy :delete_files after_destroy :delete_files
after_destroy :delete_remote_files after_destroy :delete_remote_files
after_save :create_version after_save :create_version
@@ -31,6 +31,7 @@ class Post < ActiveRecord::Base
has_many :disapprovals, :class_name => "PostDisapproval", :dependent => :destroy has_many :disapprovals, :class_name => "PostDisapproval", :dependent => :destroy
validates_uniqueness_of :md5 validates_uniqueness_of :md5
validates_presence_of :parent, :if => lambda {|rec| !rec.parent_id.nil?} validates_presence_of :parent, :if => lambda {|rec| !rec.parent_id.nil?}
validate :post_is_not_its_own_parent
attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :as => [:member, :builder, :gold, :platinum, :contributor, :janitor, :moderator, :admin, :default] attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :as => [:member, :builder, :gold, :platinum, :contributor, :janitor, :moderator, :admin, :default]
attr_accessible :is_rating_locked, :is_note_locked, :as => [:builder, :contributor, :janitor, :moderator, :admin] attr_accessible :is_rating_locked, :is_note_locked, :as => [:builder, :contributor, :janitor, :moderator, :admin]
attr_accessible :is_status_locked, :as => [:admin] attr_accessible :is_status_locked, :as => [:admin]
@@ -313,20 +314,24 @@ class Post < ActiveRecord::Base
end end
def increment_tag_post_counts def increment_tag_post_counts
Post.execute_sql("UPDATE tags SET post_count = post_count + 1 WHERE name IN (?)", tag_array) if tag_array.any? Tag.update_all("post_count = post_count + 1", {:name => tag_array}) if tag_array.any?
end end
def decrement_tag_post_counts def decrement_tag_post_counts
Post.execute_sql("UPDATE tags SET post_count = post_count - 1 WHERE name IN (?)", tag_array) if tag_array.any? Tag.update_all("post_count = post_count - 1", {:name => tag_array}) if tag_array.any?
end end
def update_tag_post_counts def update_tag_post_counts
decrement_tags = tag_array_was - tag_array decrement_tags = tag_array_was - tag_array
increment_tags = tag_array - tag_array_was increment_tags = tag_array - tag_array_was
Post.execute_sql("UPDATE tags SET post_count = post_count - 1 WHERE name IN (?)", decrement_tags) if decrement_tags.any? if increment_tags.any?
Post.execute_sql("UPDATE tags SET post_count = post_count + 1 WHERE name IN (?)", increment_tags) if increment_tags.any? Tag.update_all("post_count = post_count + 1", {:name => increment_tags})
Post.expire_cache_for_all(decrement_tags) if decrement_tags.any? Post.expire_cache_for_all(increment_tags)
Post.expire_cache_for_all(increment_tags) if increment_tags.any? end
if decrement_tags.any?
Tag.update_all("post_count = post_count - 1", {:name => decrement_tags})
Post.expire_cache_for_all(decrement_tags)
end
Post.expire_cache_for_all([""]) if new_record? || id <= 100_000 Post.expire_cache_for_all([""]) if new_record? || id <= 100_000
end end
@@ -337,7 +342,7 @@ class Post < ActiveRecord::Base
self.tag_count_copyright = 0 self.tag_count_copyright = 0
self.tag_count_character = 0 self.tag_count_character = 0
categories = Tag.categories_for(tag_array) categories = Tag.categories_for(tag_array, :disable_caching => true)
categories.each_value do |category| categories.each_value do |category|
self.tag_count += 1 self.tag_count += 1
@@ -622,11 +627,9 @@ class Post < ActiveRecord::Base
def vote!(score) def vote!(score)
if can_be_voted_by?(CurrentUser.user) if can_be_voted_by?(CurrentUser.user)
if score == "up" if score == "up"
increment!(:score) Post.update_all("score = score + 1, up_score = up_score + 1", {:id => id})
increment!(:up_score)
elsif score == "down" elsif score == "down"
decrement!(:score) Post.update_all("score = score - 1, down_score = down_score - 1", {:id => id})
decrement!(:down_score)
end end
votes.create(:score => score) votes.create(:score => score)
@@ -798,6 +801,13 @@ class Post < ActiveRecord::Base
update_column(:score, 0) update_column(:score, 0)
end end
def post_is_not_its_own_parent
if parent_id.present? && id == parent_id
errors[:base] << "Post cannot have itself as a parent"
false
end
end
end end
module DeletionMethods module DeletionMethods
@@ -860,6 +870,8 @@ class Post < ActiveRecord::Base
module VersionMethods module VersionMethods
def create_version def create_version
return if disable_versioning
if created_at == updated_at if created_at == updated_at
CurrentUser.increment!(:post_update_count) CurrentUser.increment!(:post_update_count)
versions.create( versions.create(

View File

@@ -68,9 +68,6 @@ class PostFlag < ActiveRecord::Base
if post.is_deleted? if post.is_deleted?
errors[:post] << "is deleted" errors[:post] << "is deleted"
false false
elsif post.is_pending?
errors[:post] << "is pending"
false
else else
true true
end end

View File

@@ -1,5 +1,5 @@
class Tag < ActiveRecord::Base class Tag < ActiveRecord::Base
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|-pool|pool|-fav|fav|sub|md5|-rating|rating|-locked|locked|width|height|mpixels|score|favcount|filesize|source|id|-id|date|age|order|-status|status|tagcount|gentags|arttags|chartags|copytags|parent|-parent|pixiv_id|pixiv" METATAGS = "-user|user|-approver|approver|commenter|comm|noter|-pool|pool|-fav|fav|sub|md5|-rating|rating|-locked|locked|width|height|mpixels|score|favcount|filesize|source|-source|id|-id|date|age|order|-status|status|tagcount|gentags|arttags|chartags|copytags|parent|-parent|pixiv_id|pixiv"
attr_accessible :category attr_accessible :category
has_one :wiki_page, :foreign_key => "name", :primary_key => "title" has_one :wiki_page, :foreign_key => "name", :primary_key => "title"
@@ -66,20 +66,21 @@ class Tag < ActiveRecord::Base
select_value_sql("SELECT category FROM tags WHERE name = ?", tag_name).to_i select_value_sql("SELECT category FROM tags WHERE name = ?", tag_name).to_i
end end
def category_for(tag_name) def category_for(tag_name, options = {})
Cache.get("tc:#{Cache.sanitize(tag_name)}") do if options[:disable_caching]
select_category_for(tag_name) select_category_for(tag_name)
else
Cache.get("tc:#{Cache.sanitize(tag_name)}") do
select_category_for(tag_name)
end
end end
end end
def categories_for(tag_names) def categories_for(tag_names, options = {})
Array(tag_names).inject({}) do |hash, tag_name| Array(tag_names).inject({}) do |hash, tag_name|
hash[tag_name] = category_for(tag_name) hash[tag_name] = category_for(tag_name, options)
hash hash
end end
# Cache.get_multi(tag_names, "tc") do |name|
# select_category_for(name)
# end
end end
end end
@@ -104,11 +105,7 @@ class Tag < ActiveRecord::Base
Post.raw_tag_match(name).find_each do |post| Post.raw_tag_match(name).find_each do |post|
post.reload post.reload
post.set_tag_counts post.set_tag_counts
post.update_column(:tag_count, post.tag_count) Post.update_all({:tag_count => post.tag_count, :tag_count_general => post.tag_count_general, :tag_count_artist => post.tag_count_artist, :tag_count_copyright => post.tag_count_copyright, :tag_count_character => post.tag_count_character}, {:id => post.id})
post.update_column(:tag_count_general, post.tag_count_general)
post.update_column(:tag_count_artist, post.tag_count_artist)
post.update_column(:tag_count_copyright, post.tag_count_copyright)
post.update_column(:tag_count_character, post.tag_count_character)
end end
end end
end end
@@ -253,7 +250,7 @@ class Tag < ActiveRecord::Base
return [:gt, parse_cast($1, type)] return [:gt, parse_cast($1, type)]
when /,/ when /,/
return [:in, range.split(/,/)] return [:in, range.split(/,/).map {|x| parse_cast(x, type)}]
else else
return [:eq, parse_cast(range, type)] return [:eq, parse_cast(range, type)]
@@ -402,6 +399,9 @@ class Tag < ActiveRecord::Base
when "source" when "source"
q[:source] = ($2.to_escaped_for_sql_like + "%").gsub(/%+/, '%') q[:source] = ($2.to_escaped_for_sql_like + "%").gsub(/%+/, '%')
when "-source"
q[:source_neg] = ($2.to_escaped_for_sql_like + "%").gsub(/%+/, '%')
when "date" when "date"
q[:date] = parse_helper($2, :date) q[:date] = parse_helper($2, :date)
@@ -547,14 +547,20 @@ class Tag < ActiveRecord::Base
elsif params[:order] == "date" elsif params[:order] == "date"
q = q.reorder("id desc") q = q.reorder("id desc")
elsif params[:order] == "count"
q = q.reorder("post_count desc")
elsif params[:sort] == "date" elsif params[:sort] == "date"
q = q.reorder("id desc") q = q.reorder("id desc")
elsif params[:sort] == "name" elsif params[:sort] == "name"
q = q.reorder("name") q = q.reorder("name")
else elsif params[:sort] == "count"
q = q.reorder("post_count desc") q = q.reorder("post_count desc")
else
q = q.reorder("id desc")
end end
q q

View File

@@ -130,6 +130,7 @@ class TagAlias < ActiveRecord::Base
escaped_antecedent_name = Regexp.escape(antecedent_name) escaped_antecedent_name = Regexp.escape(antecedent_name)
fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{consequent_name} ").strip fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{consequent_name} ").strip
CurrentUser.scoped(creator, creator_ip_addr) do CurrentUser.scoped(creator, creator_ip_addr) do
post.disable_versioning = true
post.update_attributes( post.update_attributes(
:tag_string => fixed_tags :tag_string => fixed_tags
) )
@@ -139,4 +140,27 @@ class TagAlias < ActiveRecord::Base
antecedent_tag.fix_post_count if antecedent_tag antecedent_tag.fix_post_count if antecedent_tag
consequent_tag.fix_post_count if consequent_tag consequent_tag.fix_post_count if consequent_tag
end end
def rename_wiki_and_artist
antecedent_wiki = WikiPage.titled(antecedent_name).first
if antecedent_wiki.present? && WikiPage.titled(consequent_name).blank?
CurrentUser.scoped(creator, creator_ip_addr) do
antecedent_wiki.update_attributes(
:title => consequent_name,
:body => "[i]This page was automatically renamed from [[#{antecedent_name}]] by a tag alias.[/i]\n\n#{antecedent_wiki.body}"
)
end
end
if antecedent_tag.category == Tag.categories.artist
antecedent_artist = Artist.name_matches(antecedent_name).first
if antecedent_artist.present? && Artist.name_matches(consequent_name).blank?
CurrentUser.scoped(creator, creator_ip_addr) do
antecedent_artist.update_attributes(
:name => consequent_name
)
end
end
end
end
end end

View File

@@ -1,6 +1,8 @@
class TagImplication < ActiveRecord::Base class TagImplication < ActiveRecord::Base
before_save :update_descendant_names before_save :update_descendant_names
after_save :update_descendant_names_for_parent after_save :update_descendant_names_for_parent
after_destroy :update_descendant_names_for_parent
after_destroy :update_posts_for_destroy
belongs_to :creator, :class_name => "User" belongs_to :creator, :class_name => "User"
before_validation :initialize_creator, :on => :create before_validation :initialize_creator, :on => :create
before_validation :normalize_names before_validation :normalize_names
@@ -90,13 +92,41 @@ class TagImplication < ActiveRecord::Base
q = q.where("antecedent_name = ?", params[:antecedent_name]) q = q.where("antecedent_name = ?", params[:antecedent_name])
end end
if params[:consequent_name].present?
q = q.where("consequent_name = ?", params[:consequent_name])
end
q q
end end
end end
module DeletionMethods
extend ActiveSupport::Concern
module ClassMethods
def update_posts_for_destroy(creator_id, creator_ip_addr, tag_name)
Post.tag_match("#{tag_name} status:any").find_each do |post|
escaped_tag_name = Regexp.escape(tag_name)
fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_tag_name}(?:\Z| )/, " ").strip
CurrentUser.scoped(User.find(creator_id), creator_ip_addr) do
post.disable_versioning = true
post.update_attributes(
:tag_string => fixed_tags
)
end
end
end
end
def update_posts_for_destroy
TagImplication.delay(:queue => "default").update_posts_for_destroy(CurrentUser.user.id, CurrentUser.ip_addr, consequent_name)
end
end
include DescendantMethods include DescendantMethods
include ParentMethods include ParentMethods
extend SearchMethods extend SearchMethods
include DeletionMethods
def initialize_creator def initialize_creator
self.creator_id = CurrentUser.user.id self.creator_id = CurrentUser.user.id
@@ -105,7 +135,7 @@ class TagImplication < ActiveRecord::Base
def process! def process!
update_column(:status, "processing") update_column(:status, "processing")
update_posts update_posts_for_create
update_column(:status, "active") update_column(:status, "active")
update_descendant_names_for_parent update_descendant_names_for_parent
rescue Exception => e rescue Exception => e
@@ -120,11 +150,12 @@ class TagImplication < ActiveRecord::Base
end end
end end
def update_posts def update_posts_for_create
Post.tag_match("#{antecedent_name} status:any").find_each do |post| Post.tag_match("#{antecedent_name} status:any").find_each do |post|
escaped_antecedent_name = Regexp.escape(antecedent_name) escaped_antecedent_name = Regexp.escape(antecedent_name)
fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{antecedent_name} #{descendant_names} ").strip fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{antecedent_name} #{descendant_names} ").strip
CurrentUser.scoped(creator, creator_ip_addr) do CurrentUser.scoped(creator, creator_ip_addr) do
post.disable_versioning = true
post.update_attributes( post.update_attributes(
:tag_string => fixed_tags :tag_string => fixed_tags
) )

View File

@@ -6,7 +6,7 @@ class TagSubscription < ActiveRecord::Base
before_save :limit_tag_count before_save :limit_tag_count
attr_accessible :name, :tag_query, :post_ids, :is_public, :is_visible_on_profile attr_accessible :name, :tag_query, :post_ids, :is_public, :is_visible_on_profile
validates_presence_of :name, :tag_query, :creator_id validates_presence_of :name, :tag_query, :creator_id
validates_format_of :tag_query, :with => /^(?:\S+\s*){1,20}$/m, :message => "can have up to 20 tags" validates_format_of :tag_query, :with => /\A(?:\S*\s*){1,20}\Z/, :message => "can have up to 20 tags"
validate :creator_can_create_subscriptions, :on => :create validate :creator_can_create_subscriptions, :on => :create
def normalize_name def normalize_name
@@ -124,7 +124,13 @@ class TagSubscription < ActiveRecord::Base
end end
def self.find_posts(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit) def self.find_posts(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit)
Post.where(["id in (?)", find_post_ids(user_id, name, limit)]).order("id DESC").limit(limit) arel = Post.where(["id in (?)", find_post_ids(user_id, name, limit)])
if CurrentUser.user.hide_deleted_posts?
arel = arel.where("is_deleted = false")
end
arel.order("id DESC").limit(limit)
end end
def self.process_all def self.process_all

View File

@@ -40,7 +40,8 @@ class User < ActiveRecord::Base
before_create :promote_to_admin_if_first_user before_create :promote_to_admin_if_first_user
has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy
has_many :posts, :foreign_key => "uploader_id" has_many :posts, :foreign_key => "uploader_id"
has_one :ban has_many :bans, :order => "bans.id desc"
has_one :recent_ban, :class_name => "Ban", :order => "bans.id desc"
has_many :subscriptions, :class_name => "TagSubscription", :foreign_key => "creator_id", :order => "name" has_many :subscriptions, :class_name => "TagSubscription", :foreign_key => "creator_id", :order => "name"
has_many :note_versions, :foreign_key => "updater_id" has_many :note_versions, :foreign_key => "updater_id"
has_many :dmails, :foreign_key => "owner_id", :order => "dmails.id desc" has_many :dmails, :foreign_key => "owner_id", :order => "dmails.id desc"
@@ -351,7 +352,7 @@ class User < ActiveRecord::Base
def create_mod_action def create_mod_action
if level_changed? if level_changed?
ModAction.create(:description => "#{name} level changed #{level_string(level_was)} -> #{level_string} by #{CurrentUser.name}") ModAction.create(:description => %{"#{name}":/users/#{id} level changed #{level_string(level_was)} -> #{level_string}})
end end
end end
@@ -510,13 +511,15 @@ class User < ActiveRecord::Base
module ApiMethods module ApiMethods
def hidden_attributes def hidden_attributes
super + [:password_hash, :bcrypt_password_hash, :email, :email_verification_key, :time_zone, :created_at, :updated_at, :receive_email_notifications, :last_logged_in_at, :last_forum_read_at, :has_mail, :default_image_size, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :base_upload_limit, :recent_tags, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :enable_sequential_post_navigation, :hide_deleted_posts, :per_page, :style_usernames] super + [:password_hash, :bcrypt_password_hash, :email, :email_verification_key, :time_zone, :updated_at, :receive_email_notifications, :last_logged_in_at, :last_forum_read_at, :has_mail, :default_image_size, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :recent_tags, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :enable_sequential_post_navigation, :hide_deleted_posts, :per_page, :style_usernames]
end end
def serializable_hash(options = {}) def serializable_hash(options = {})
options ||= {} options ||= {}
options[:except] ||= [] options[:except] ||= []
options[:except] += hidden_attributes options[:except] += hidden_attributes
options[:methods] ||= []
options[:methods] += [:wiki_page_version_count, :artist_version_count, :pool_version_count, :forum_post_count, :comment_count]
super(options) super(options)
end end
@@ -525,6 +528,8 @@ class User < ActiveRecord::Base
options ||= {} options ||= {}
options[:except] ||= [] options[:except] ||= []
options[:except] += hidden_attributes options[:except] += hidden_attributes
options[:methods] ||= []
options[:methods] += [:wiki_page_version_count, :artist_version_count, :pool_version_count, :forum_post_count, :comment_count]
super(options, &block) super(options, &block)
end end
@@ -538,6 +543,28 @@ class User < ActiveRecord::Base
end end
end end
module CountMethods
def wiki_page_version_count
WikiPageVersion.for_user(id).count
end
def artist_version_count
ArtistVersion.for_user(id).count
end
def pool_version_count
PoolVersion.for_user(id).count
end
def forum_post_count
ForumPost.for_user(id).count
end
def comment_count
Comment.for_creator(id).count
end
end
module SearchMethods module SearchMethods
def named(name) def named(name)
where("lower(name) = ?", name) where("lower(name) = ?", name)
@@ -657,6 +684,7 @@ class User < ActiveRecord::Base
include LimitMethods include LimitMethods
include InvitationMethods include InvitationMethods
include ApiMethods include ApiMethods
include CountMethods
extend SearchMethods extend SearchMethods
include DeletionMethods include DeletionMethods

View File

@@ -5,6 +5,7 @@ class UserFeedback < ActiveRecord::Base
before_validation :initialize_creator, :on => :create before_validation :initialize_creator, :on => :create
attr_accessible :body, :user_id, :category, :user_name attr_accessible :body, :user_id, :category, :user_name
validates_presence_of :user, :creator, :body, :category validates_presence_of :user, :creator, :body, :category
validates_inclusion_of :category, :in => %w(positive negative neutral)
validate :creator_is_gold validate :creator_is_gold
validate :user_is_not_creator validate :user_is_not_creator
after_create :create_dmail after_create :create_dmail
@@ -46,6 +47,10 @@ class UserFeedback < ActiveRecord::Base
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].mb_chars.downcase) q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].mb_chars.downcase)
end end
if params[:category].present?
q = q.where("category = ?", params[:category])
end
q q
end end
end end

View File

@@ -166,7 +166,7 @@ class PostPresenter < Presenter
end end
else else
first = true first = true
@post.pools.active.each do |pool| @post.pools.each do |pool|
if first && template.params[:tags].blank? if first && template.params[:tags].blank?
html += pool_link_html(template, pool, :include_rel => true) html += pool_link_html(template, pool, :include_rel => true)
first = false first = false
@@ -181,7 +181,7 @@ class PostPresenter < Presenter
end end
def pool_link_html(template, pool, options = {}) def pool_link_html(template, pool, options = {})
pool_html = ['<li id="nav-link-for-pool-#{pool.id}">'] pool_html = ["<li id='nav-link-for-pool-#{pool.id}'>"]
match_found = false match_found = false
if options[:include_rel] if options[:include_rel]
@@ -194,11 +194,17 @@ class PostPresenter < Presenter
klass = "" klass = ""
end end
if @post.id != pool.post_id_array.first
pool_html << template.link_to("&laquo;".html_safe, template.post_path(pool.post_id_array.first, :pool_id => pool.id), :class => "#{klass} first")
else
pool_html << '<span class="first">&laquo;</span>'
end
if pool.neighbors(@post).previous if pool.neighbors(@post).previous
pool_html << template.link_to("&laquo;prev".html_safe, template.post_path(pool.neighbors(@post).previous, :pool_id => pool.id), :rel => prev_rel, :class => "#{klass} prev") pool_html << template.link_to("&lsaquo;&thinsp;prev".html_safe, template.post_path(pool.neighbors(@post).previous, :pool_id => pool.id), :rel => prev_rel, :class => "#{klass} prev")
match_found = true match_found = true
else else
pool_html << '<span class="prev">&laquo;prev</span>' pool_html << '<span class="prev">&lsaquo;&thinsp;prev</span>'
end end
pool_html << ' <span class="pool-name ' + klass + '">' pool_html << ' <span class="pool-name ' + klass + '">'
@@ -206,10 +212,16 @@ class PostPresenter < Presenter
pool_html << '</span> ' pool_html << '</span> '
if pool.neighbors(@post).next if pool.neighbors(@post).next
pool_html << template.link_to("next&raquo;".html_safe, template.post_path(pool.neighbors(@post).next, :pool_id => pool.id), :rel => next_rel, :class => "#{klass} next") pool_html << template.link_to("next&thinsp;&rsaquo;".html_safe, template.post_path(pool.neighbors(@post).next, :pool_id => pool.id), :rel => next_rel, :class => "#{klass} next")
match_found = true match_found = true
else else
pool_html << '<span class="next">next&raquo;</span>' pool_html << '<span class="next">next&thinsp;&rsaquo;</span>'
end
if @post.id != pool.post_id_array.last
pool_html << template.link_to("&raquo;".html_safe, template.post_path(pool.post_id_array.last, :pool_id => pool.id), :class => "#{klass} last")
else
pool_html << '<span class="last">&raquo;</span>'
end end
pool_html << "</li>" pool_html << "</li>"

View File

@@ -13,6 +13,7 @@ module PostSetPresenters
posts.each do |post| posts.each do |post|
html << PostPresenter.preview(post, :tags => @post_set.tag_string) html << PostPresenter.preview(post, :tags => @post_set.tag_string)
html << "\n"
end end
html.html_safe html.html_safe

View File

@@ -1,5 +1,5 @@
module PostSetPresenters module PostSetPresenters
class WikiPage < Post class WikiPage < PostSetPresenters::Post
def posts def posts
@post_set.posts @post_set.posts
rescue ActiveRecord::StatementInvalid, PGError rescue ActiveRecord::StatementInvalid, PGError

View File

@@ -19,7 +19,7 @@ class UserPresenter
def ban_reason def ban_reason
if user.is_banned? if user.is_banned?
"#{user.ban.reason}; expires #{user.ban.expires_at}" "#{user.recent_ban.reason}; expires #{user.recent_ban.expires_at} (#{user.bans.count} bans total)"
else else
nil nil
end end
@@ -80,7 +80,7 @@ class UserPresenter
end end
def comment_count(template) def comment_count(template)
template.link_to(Comment.for_creator(user.id).count, template.comments_path(:search => {:creator_id => user.id}, :group_by => "comment")) template.link_to(user.comment_count, template.comments_path(:search => {:creator_id => user.id}, :group_by => "comment"))
end end
def commented_posts_count(template) def commented_posts_count(template)
@@ -100,19 +100,19 @@ class UserPresenter
end end
def wiki_page_version_count(template) def wiki_page_version_count(template)
template.link_to(WikiPageVersion.for_user(user.id).count, template.wiki_page_versions_path(:search => {:updater_id => user.id})) template.link_to(user.wiki_page_version_count, template.wiki_page_versions_path(:search => {:updater_id => user.id}))
end end
def artist_version_count(template) def artist_version_count(template)
template.link_to(ArtistVersion.for_user(user.id).count, template.artist_versions_path(:search => {:updater_id => user.id})) template.link_to(user.artist_version_count, template.artist_versions_path(:search => {:updater_id => user.id}))
end end
def forum_post_count(template) def forum_post_count(template)
template.link_to(ForumPost.for_user(user.id).count, template.forum_posts_path(:search => {:creator_id => user.id})) template.link_to(user.forum_post_count, template.forum_posts_path(:search => {:creator_id => user.id}))
end end
def pool_version_count(template) def pool_version_count(template)
template.link_to(PoolVersion.for_user(user.id).count, template.pool_versions_path(:search => {:updater_id => user.id})) template.link_to(user.pool_version_count, template.pool_versions_path(:search => {:updater_id => user.id}))
end end
def inviter(template) def inviter(template)

View File

@@ -26,6 +26,13 @@ create implication aaa -> bbb
<%= text_field "batch", "forum_id" %> <%= text_field "batch", "forum_id" %>
</div> </div>
<div class="input">
<label for="batch_rename_aliased_pages">
<%= check_box "batch", "rename_aliased_pages" %>
Automatically rename all wiki pages and artists for aliases in this batch
</label>
</div>
<%= submit_tag %> <%= submit_tag %>
<% end %> <% end %>
</div> </div>

View File

@@ -5,7 +5,7 @@
<th><label for="search_name">Name</label> <th><label for="search_name">Name</label>
<td> <td>
<div class="input"> <div class="input">
<%= text_field "search", "name" %> <%= text_field "search", "name", :value => params[:search][:name] %>
<span class="hint">You can search on any name or URL</span> <span class="hint">You can search on any name or URL</span>
</div> </div>
</td> </td>
@@ -15,7 +15,7 @@
<th><label for="search_sort">Sort</label> <th><label for="search_sort">Sort</label>
<td> <td>
<div class="input"> <div class="input">
<%= select "search", "sort", [["Date", "date"], ["Name", "name"]] %> <%= select "search", "sort", [["Date", "date"], ["Name", "name"]], :selected => params[:search][:sort] %>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -7,14 +7,14 @@
<li><%= link_to "Recent changes", artist_versions_path %></li> <li><%= link_to "Recent changes", artist_versions_path %></li>
<% if @artist && !@artist.new_record? %> <% if @artist && !@artist.new_record? %>
<li>|</li> <li>|</li>
<li><%= link_to "Posts", posts_path(:tags => @artist.name) %></li> <li><%= link_to "Posts (#{Post.fast_count(@artist.name)})", posts_path(:tags => @artist.name) %></li>
<li><%= link_to "Show", artist_path(@artist) %></li> <li><%= link_to "Show", artist_path(@artist) %></li>
<% if CurrentUser.is_member? %> <% if CurrentUser.is_member? %>
<li><%= link_to "Edit", edit_artist_path(@artist) %></li> <li><%= link_to "Edit", edit_artist_path(@artist) %></li>
<% end %> <% end %>
<li><%= link_to "History", artist_versions_path(:search => {:artist_id => @artist.id}) %></li> <li><%= link_to "History", artist_versions_path(:search => {:artist_id => @artist.id}) %></li>
<% if CurrentUser.is_admin? %> <% if CurrentUser.is_admin? %>
<%= link_to "Ban", ban_artist_path(@artist), :method => :put %> <%= link_to "Ban", ban_artist_path(@artist), :method => :put, :confirm => "Are you sure you want to ban this artist?" %>
<% end %> <% end %>
<% end %> <% end %>
</menu> </menu>

View File

@@ -4,6 +4,7 @@
<%= form_tag(comments_path, :class => "simple_form") do %> <%= form_tag(comments_path, :class => "simple_form") do %>
<%= hidden_field "comment", "post_id", :value => post.id %> <%= hidden_field "comment", "post_id", :value => post.id %>
<%= dtext_field "comment", "body", :input_id => "comment_response_for_#{post.id}", :preview_id => "dtext-preview-for-#{post.id}" %> <%= dtext_field "comment", "body", :input_id => "comment_response_for_#{post.id}", :preview_id => "dtext-preview-for-#{post.id}" %>
<%= submit_tag "Post" %>
<%= dtext_preview_button "comment", "body", :input_id => "comment_response_for_#{post.id}", :preview_id => "dtext-preview-for-#{post.id}" %> <%= dtext_preview_button "comment", "body", :input_id => "comment_response_for_#{post.id}", :preview_id => "dtext-preview-for-#{post.id}" %>
<%= submit_tag "Post" %> <%= check_box "comment", "do_not_bump_post", :id => "comment_do_not_bump_post_#{post.id}" %> <label for="comment_do_not_bump_post_<%= post.id %>">No bump</label> <%= check_box "comment", "do_not_bump_post", :id => "comment_do_not_bump_post_#{post.id}" %> <label for="comment_do_not_bump_post_<%= post.id %>">No bump</label>
<% end %> <% end %>

View File

@@ -19,7 +19,7 @@
<% if @post || @posts %> <% if @post || @posts %>
<li><%= link_to "Reply", new_comment_path(:post_id => comment.post_id), :class => "reply-link", "data-comment-id" => comment.id %></li> <li><%= link_to "Reply", new_comment_path(:post_id => comment.post_id), :class => "reply-link", "data-comment-id" => comment.id %></li>
<% if comment.editable_by?(CurrentUser.user) %> <% if comment.editable_by?(CurrentUser.user) %>
<li><%= link_to "Delete", comment_path(comment.id), :confirm => "Do you really want to delete this comment?", :method => :delete, :remote => true %></li> <li><%= link_to "Delete", comment_path(comment.id), :confirm => "Are you sure you want to delete this comment?", :method => :delete, :remote => true %></li>
<li><%= link_to "Edit", edit_comment_path(comment.id) %></li> <li><%= link_to "Edit", edit_comment_path(comment.id) %></li>
<% end %> <% end %>
<li id="comment-vote-up-link-for-<%= comment.id %>"><%= link_to "Vote up", comment_votes_path(:comment_id => comment.id, :score => "up"), :method => :post, :remote => true %></li> <li id="comment-vote-up-link-for-<%= comment.id %>"><%= link_to "Vote up", comment_votes_path(:comment_id => comment.id, :score => "up"), :method => :post, :remote => true %></li>

View File

@@ -34,3 +34,7 @@
</table> </table>
<%= numbered_paginator(@delayed_jobs) %> <%= numbered_paginator(@delayed_jobs) %>
<% content_for(:page_title) do %>
Delayed Jobs - <%= Danbooru.config.app_name %>
<% end %>

View File

@@ -1,6 +1,6 @@
<% content_for(:secondary_links) do %> <% content_for(:secondary_links) do %>
<menu> <menu>
<li><%= link_to "All", dmails_path %></li> <li><%= link_to "All", dmails_path(:search => {:owner_id => CurrentUser.id}, :folder => "all") %></li>
<li><%= link_to "Received", dmails_path(:search => {:owner_id => CurrentUser.id, :to_id => CurrentUser.id}, :folder => "received") %></li> <li><%= link_to "Received", dmails_path(:search => {:owner_id => CurrentUser.id, :to_id => CurrentUser.id}, :folder => "received") %></li>
<li><%= link_to "Sent", dmails_path(:search => {:owner_id => CurrentUser.id, :from_id => CurrentUser.id}, :folder => "sent") %></li> <li><%= link_to "Sent", dmails_path(:search => {:owner_id => CurrentUser.id, :from_id => CurrentUser.id}, :folder => "sent") %></li>
<li><%= link_to "New", new_dmail_path %></li> <li><%= link_to "New", new_dmail_path %></li>

View File

@@ -1 +0,0 @@
<%= post.favorited_users.reverse_each.map{|user| link_to_user(user)}.join(", ").html_safe %>

View File

@@ -5,5 +5,11 @@
$("a#remove-from-favorites").show(); $("a#remove-from-favorites").show();
$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); $("#score-for-post-<%= @post.id %>").html(<%= @post.score %>);
$("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); $("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>);
<% if CurrentUser.is_gold? %>
$("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>");
if (!$("#favlist").is(":visible")) {
$("#show-favlist-link").show();
}
<% end %>
Danbooru.notice("You have favorited this post"); Danbooru.notice("You have favorited this post");
<% end %> <% end %>

View File

@@ -2,4 +2,10 @@ $("a#add-to-favorites").show();
$("a#remove-from-favorites").hide(); $("a#remove-from-favorites").hide();
$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); $("#score-for-post-<%= @post.id %>").html(<%= @post.score %>);
$("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); $("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>);
<% if CurrentUser.is_gold? %>
$("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>");
<% if @post.fav_count == 0 %>
$("#show-favlist-link, #hide-favlist-link, #favlist").hide();
<% end %>
<% end %>
Danbooru.notice("You have unfavorited this post"); Danbooru.notice("You have unfavorited this post");

View File

@@ -1,3 +0,0 @@
$("#favlist").html("<%= j(render(:partial => "favorites/favorited_users_list", :locals => { :post => @post }))%>");
$("#show-favlist-link").attr("href", "#").removeAttr("data-remote");

View File

@@ -1,5 +1,5 @@
<% if CurrentUser.is_janitor? || !forum_post.is_deleted? %> <% if CurrentUser.is_janitor? || !forum_post.is_deleted? %>
<article data-forum-post-id="<%= forum_post.id %>"> <article id="forum_post_<%= forum_post.id %>" data-forum-post-id="<%= forum_post.id %>">
<div class="author"> <div class="author">
<h4> <h4>
<%= link_to_user forum_post.creator %> <%= link_to_user forum_post.creator %>
@@ -37,8 +37,11 @@
<li><%= link_to "Edit", edit_forum_post_path(forum_post.id) %></li> <li><%= link_to "Edit", edit_forum_post_path(forum_post.id) %></li>
<% end %> <% end %>
<% end %> <% end %>
<li><%= link_to "Parent", forum_topic_path(forum_post.topic, :page => forum_post.forum_topic_page) %></li> <% if params[:controller] == "forum_posts" %>
<li><%= link_to "Permalink", forum_post_path(forum_post) %></li> <li><%= link_to "Parent", forum_topic_path(forum_post.topic, :page => forum_post.forum_topic_page, :anchor => "forum_post_#{forum_post.id}") %></li>
<% else %>
<li><%= link_to "Permalink", forum_post_path(forum_post) %></li>
<% end %>
</menu> </menu>
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@@ -7,8 +7,8 @@
<%= nav_link_to("Posts", posts_path) %> <%= nav_link_to("Posts", posts_path) %>
<%= nav_link_to("Comments", comments_path(:group_by => "post")) %> <%= nav_link_to("Comments", comments_path(:group_by => "post")) %>
<%= nav_link_to("Notes", notes_path(:group_by => "post")) %> <%= nav_link_to("Notes", notes_path(:group_by => "post")) %>
<%= nav_link_to("Artists", artists_path(:search => {:order => "date"})) %> <%= nav_link_to("Artists", artists_path) %>
<%= nav_link_to("Tags", tags_path(:search => {:order => "date"})) %> <%= nav_link_to("Tags", tags_path) %>
<% if CurrentUser.is_moderator? %> <% if CurrentUser.is_moderator? %>
<%= nav_link_to("Aliases", tag_aliases_path) %> <%= nav_link_to("Aliases", tag_aliases_path) %>
<%= nav_link_to("Implications", tag_implications_path) %> <%= nav_link_to("Implications", tag_implications_path) %>

View File

@@ -11,7 +11,7 @@
<%= Danbooru.config.custom_html_header_content %> <%= Danbooru.config.custom_html_header_content %>
<%= yield :html_header %> <%= yield :html_header %>
</head> </head>
<body> <body lang="en">
<div id="page"> <div id="page">
<%= yield :layout %> <%= yield :layout %>
</div> </div>

View File

@@ -22,7 +22,7 @@
<%= raw Danbooru.config.custom_html_header_content %> <%= raw Danbooru.config.custom_html_header_content %>
<%= yield :html_header %> <%= yield :html_header %>
</head> </head>
<body> <body lang="en">
<header id="top"> <header id="top">
<%= render "news_updates/listing" %> <%= render "news_updates/listing" %>
@@ -56,11 +56,10 @@
<%= render "users/tos" %> <%= render "users/tos" %>
<% end %> <% end %>
<%- if flash[:notice] -%> <div class="ui-corner-all ui-state-highlight" id="notice" style="<%= "display: none;" unless flash[:notice] %>">
<div class="ui-corner-all ui-state-highlight" id="notice"><%= flash[:notice] %></div> <span><%= flash[:notice] %></span>
<%- else -%> <a href="#" id="close-notice-link">close</a>
<div class="ui-corner-all ui-state-highlight" id="notice" style="display: none;"></div> </div>
<%- end -%>
<%= yield :layout %> <%= yield :layout %>
</div> </div>

View File

@@ -1,5 +1,5 @@
<% cache("news-updates", :expires_in => 1.hour) do %> <% cache("news-updates", :expires_in => 1.hour) do %>
<div id="news-updates" data-updated-at="<%= NewsUpdate.recent.first.try(:created_at).try(:strftime, "%Y-%m-%d") %>"> <div id="news-updates" data-id="<%= NewsUpdate.recent.first.try(:id) %>">
<ul> <ul>
<% NewsUpdate.recent.each do |news_update| %> <% NewsUpdate.recent.each do |news_update| %>
<li><%= news_update.created_at.strftime("%b %d") %>: <%= news_update.message.html_safe %></li> <li><%= news_update.created_at.strftime("%b %d") %>: <%= news_update.message.html_safe %></li>

View File

@@ -13,7 +13,7 @@
<tbody> <tbody>
<% @news_updates.each do |news_update| %> <% @news_updates.each do |news_update| %>
<tr id="news-update-<%= news_update.id %>"> <tr id="news-update-<%= news_update.id %>">
<td><%= news_update.creator.name %></td> <td><%= link_to_user news_update.creator %></td>
<td><%= news_update.message %></td> <td><%= news_update.message %></td>
<td><%= link_to "Edit", edit_news_update_path(news_update) %> | <%= link_to "Delete", news_update_path(news_update), :method => :delete %></td> <td><%= link_to "Edit", edit_news_update_path(news_update) %> | <%= link_to "Delete", news_update_path(news_update), :method => :delete %></td>
</tr> </tr>

View File

@@ -33,7 +33,7 @@
<td><%= compact_time pool_version.updated_at %></td> <td><%= compact_time pool_version.updated_at %></td>
<% if CurrentUser.is_member? %> <% if CurrentUser.is_member? %>
<td> <td>
<%= link_to "Revert", revert_pool_path(pool_version.pool_id, :version => pool_version.id) %> <%= link_to "Revert", revert_pool_path(pool_version.pool_id, :version_id => pool_version.id), :method => :put, :remote => true %>
</td> </td>
<% end %> <% end %>
</tr> </tr>

View File

@@ -5,7 +5,7 @@
<th><label for="search_name_matches">Name</label></th> <th><label for="search_name_matches">Name</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= text_field "search", "name_matches" %> <%= text_field "search", "name_matches", :value => params[:search][:name_matches] %>
</div> </div>
</td> </td>
</tr> </tr>
@@ -14,7 +14,7 @@
<th><label for="search_description_matches">Description</label></th> <th><label for="search_description_matches">Description</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= text_field "search", "description_matches" %> <%= text_field "search", "description_matches", :value => params[:search][:description_matches] %>
</div> </div>
</td> </td>
</tr> </tr>
@@ -23,7 +23,7 @@
<th><label for="search_creator_name">Creator</th> <th><label for="search_creator_name">Creator</th>
<td> <td>
<div class="input"> <div class="input">
<%= text_field "search", "creator_name" %> <%= text_field "search", "creator_name", :value => params[:search][:creator_name] %>
</div> </div>
</td> </td>
</tr> </tr>
@@ -32,7 +32,7 @@
<th><label for="search_sort">Order</th> <th><label for="search_sort">Order</th>
<td> <td>
<div class="input"> <div class="input">
<%= select "search", "sort", [["Last updated", "updated_at"], ["Name", "name"]] %> <%= select "search", "sort", [["Last updated", "updated_at"], ["Name", "name"]], :selected => params[:search][:sort] %>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -4,6 +4,8 @@
<h1>New Pool</h1> <h1>New Pool</h1>
<%= f.input :name %> <%= f.input :name %>
<%= f.input :description %> <%= f.input :description %>
<%= f.input :post_ids, :label => "Posts" %>
<%= f.input :is_active %>
<%= f.button :submit %> <%= f.button :submit %>
<% end %> <% end %>
</div> </div>

View File

@@ -0,0 +1 @@
location.reload();

View File

@@ -3,8 +3,6 @@
<aside id="sidebar"> <aside id="sidebar">
<%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %> <%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %>
<%= render_advertisement("vertical") %>
<%= render "posts/partials/index/mode_menu" %> <%= render "posts/partials/index/mode_menu" %>
<%= render "posts/partials/index/blacklist" %> <%= render "posts/partials/index/blacklist" %>
@@ -19,18 +17,16 @@
<section id="content" class="<%= Danbooru.config.can_see_ads?(CurrentUser.user) ? "with-ads" : "without-ads" %>"> <section id="content" class="<%= Danbooru.config.can_see_ads?(CurrentUser.user) ? "with-ads" : "without-ads" %>">
<menu id="post-sections"> <menu id="post-sections">
<li class="active"><a href="#posts" id="show-posts-link">Posts</a></li> <li class="active"><a href="#" id="show-posts-link">Posts</a></li>
<% if @post_set.has_wiki? %> <% if @post_set.has_wiki? %>
<li><a href="#wiki-except" id="show-wiki-excerpt-link">Wiki</a></li> <li><%= link_to "Wiki", wiki_page_path(@post_set.wiki_page), :id => "show-wiki-excerpt-link" %></li>
<% end %> <% end %>
</menu> </menu>
<%= render "posts/partials/index/edit" %> <%= render "posts/partials/index/edit" %>
<%= render "wiki_pages/excerpt", :post_set => @post_set %> <%= render "wiki_pages/excerpt", :post_set => @post_set %>
<%= render "posts/partials/index/posts", :post_set => @post_set %> <%= render "posts/partials/index/posts", :post_set => @post_set %>
<%= render_rss_advertisement("short", @post_set.has_explicit?) %>
</section> </section>
<% content_for(:page_title) do %> <% content_for(:page_title) do %>

View File

@@ -1,6 +1,4 @@
<div id="posts"> <div id="posts">
<%= render_advertisement("horizontal") %>
<%= post_set.presenter.post_previews_html(self) %> <%= post_set.presenter.post_previews_html(self) %>
<%= numbered_paginator(post_set.posts) %> <%= numbered_paginator(post_set.posts) %>

View File

@@ -62,7 +62,7 @@
<div class="input"> <div class="input">
<div> <div>
<%= f.label :tag_string, "Tags" %> <%= f.label :tag_string, "Tags" %>
<%= f.text_area :tag_string , :size => "50x5", :value => post.presenter.categorized_tag_string + " " %> <%= f.text_area :tag_string, :size => "50x5", :value => post.presenter.categorized_tag_string + " " %>
</div> </div>
<%= button_tag "Related tags", :id => "related-tags-button", :type => "button" %> <%= button_tag "Related tags", :id => "related-tags-button", :type => "button" %>

View File

@@ -15,10 +15,10 @@
<li>Rating: <%= post.pretty_rating %></li> <li>Rating: <%= post.pretty_rating %></li>
<li>Score: <span id="score-for-post-<%= post.id %>"><%= post.score %></span> <% if CurrentUser.is_gold? %>(vote <%= link_to "up", post_votes_path(:post_id => post.id, :score => "up"), :remote => true, :method => :post %>/<%= link_to "down", post_votes_path(:post_id => post.id, :score => "down"), :remote => true, :method => :post %>)<% end %></li> <li>Score: <span id="score-for-post-<%= post.id %>"><%= post.score %></span> <% if CurrentUser.is_gold? %>(vote <%= link_to "up", post_votes_path(:post_id => post.id, :score => "up"), :remote => true, :method => :post %>/<%= link_to "down", post_votes_path(:post_id => post.id, :score => "down"), :remote => true, :method => :post %>)<% end %></li>
<li>Favorites: <span id="favcount-for-post-<%= post.id %>"><%= post.fav_count %></span> <li>Favorites: <span id="favcount-for-post-<%= post.id %>"><%= post.fav_count %></span>
<% if CurrentUser.is_gold? && post.fav_count > 0 %> <% if CurrentUser.is_gold? %>
<%= link_to "&raquo;".html_safe, favorites_path(:post_id => post.id), :remote => true, :id => "show-favlist-link" %> <%= link_to "&raquo;".html_safe, "#", :id => "show-favlist-link" %>
<%= link_to "&laquo;".html_safe, "#", :id => "hide-favlist-link" %> <%= link_to "&laquo;".html_safe, "#", :id => "hide-favlist-link" %>
<div id="favlist"></div> <div id="favlist"><%= post_favlist(post) %></div>
<% end %></li> <% end %></li>
<li> <li>
Status: Status:

View File

@@ -26,7 +26,7 @@
<% if post.is_pending? %> <% if post.is_pending? %>
<div class="ui-corner-all ui-state-highlight notice notice-pending" id="pending-approval-notice"> <div class="ui-corner-all ui-state-highlight notice notice-pending" id="pending-approval-notice">
This post is pending approval (<%= link_to "learn more", wiki_pages_path(:title => "help:post_moderation") %>) This post is pending approval (<%= link_to "learn more", wiki_pages_path(:title => "about:mod_queue") %>)
<% if CurrentUser.is_janitor? && !post.disapproved_by?(CurrentUser.user) %> <% if CurrentUser.is_janitor? && !post.disapproved_by?(CurrentUser.user) %>
<div class="quick-mod"> <div class="quick-mod">
@@ -48,8 +48,8 @@
<% if post.parent_id %> <% if post.parent_id %>
<div class="ui-corner-all ui-state-highlight notice notice-child"> <div class="ui-corner-all ui-state-highlight notice notice-child">
<%= has_parent_message(post, @parent_post_set, @siblings_post_set) %> <%= has_parent_message(post, @parent_post_set) %>
<div id="has-parent-relationship-preview"><%= @parent_post_set.presenter.post_previews_html(self) %><%= @siblings_post_set.presenter.post_previews_html(self) %></div> <div id="has-parent-relationship-preview"><%= @parent_post_set.presenter.post_previews_html(self) %></div>
</div> </div>
<% end %> <% end %>

View File

@@ -1,9 +1,9 @@
<div id="search-seq-nav"> <div id="search-seq-nav">
<ul> <ul>
<li class="active"> <li class="active">
<%= link_to "&laquo;prev".html_safe, show_seq_post_path(post, :tags => params[:tags], :seq => "prev"), :rel => "prev", :class => "prev" %> <%= link_to "&lsaquo;&thinsp;prev".html_safe, show_seq_post_path(post, :tags => params[:tags], :seq => "prev"), :rel => "prev", :class => "prev" %>
<span class="search-name">Search: <%= params[:tags] %></span> <span class="search-name">Search: <%= params[:tags] %></span>
<%= link_to "next&raquo;".html_safe, show_seq_post_path(post, :tags => params[:tags], :seq => "next"), :rel => "next", :class => "next" %> <%= link_to "next&thinsp;&rsaquo;".html_safe, show_seq_post_path(post, :tags => params[:tags], :seq => "next"), :rel => "next", :class => "next" %>
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -3,8 +3,6 @@
<aside id="sidebar"> <aside id="sidebar">
<%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %> <%= render "posts/partials/common/search", :path => posts_path, :tags => params[:tags] %>
<%= render_advertisement("vertical") %>
<%= render "posts/partials/index/blacklist" %> <%= render "posts/partials/index/blacklist" %>
<section id="tag-list"> <section id="tag-list">
@@ -42,10 +40,9 @@
<%= render "posts/partials/show/notices", :post => @post %> <%= render "posts/partials/show/notices", :post => @post %>
<%= render_advertisement("horizontal") %>
<section id="image-container" data-tags="<%= @post.tag_string %>" data-user="<%= @post.uploader_name %>" data-rating="<%= @post.rating %>" data-flags="<%= @post.status_flags %>"> <section id="image-container" data-tags="<%= @post.tag_string %>" data-user="<%= @post.uploader_name %>" data-rating="<%= @post.rating %>" data-flags="<%= @post.status_flags %>">
<div id="note-container"></div> <div id="note-container"></div>
<div id="note-preview"></div>
<%= @post.presenter.image_html(self) %> <%= @post.presenter.image_html(self) %>
</section> </section>
@@ -78,8 +75,6 @@
<section id="share" style="display: none;"> <section id="share" style="display: none;">
<%= render "posts/partials/show/share", :post => @post %> <%= render "posts/partials/show/share", :post => @post %>
</section> </section>
<%= render_rss_advertisement("long", @post.rating == "e") %>
</section> </section>
</div> </div>

View File

@@ -2,7 +2,7 @@
<div id="a-index"> <div id="a-index">
<div class="search"> <div class="search">
<%= form_tag(general_search_tag_aliases_path, :method => :get) do %> <%= form_tag(general_search_tag_aliases_path, :method => :get) do %>
<%= text_field_tag "query", params[:query] %> <%= text_field_tag "query", params[:query], :value => params[:search][:name_matches] %>
<%= submit_tag "Search Aliases" %> <%= submit_tag "Search Aliases" %>
<%= submit_tag "Search Implications" %> <%= submit_tag "Search Implications" %>
<% end %> <% end %>

View File

@@ -2,7 +2,7 @@
<div id="a-index"> <div id="a-index">
<div class="search"> <div class="search">
<%= form_tag(general_search_tag_aliases_path, :method => :get) do %> <%= form_tag(general_search_tag_aliases_path, :method => :get) do %>
<%= text_field_tag "query", params[:query] %> <%= text_field_tag "query", params[:query], :value => params[:search][:name_matches] %>
<%= submit_tag "Search Implications" %> <%= submit_tag "Search Implications" %>
<%= submit_tag "Search Aliases" %> <%= submit_tag "Search Aliases" %>
<% end %> <% end %>

View File

@@ -1,6 +1,6 @@
<%= simple_form_for(@tag_subscription) do |f| %> <%= simple_form_for(@tag_subscription) do |f| %>
<%= f.input :name %> <%= f.input :name %>
<%= f.input :tag_query, :as => :string %> <%= f.input :tag_query %>
<div class="input"> <div class="input">
<label for="tag_subscription_is_public"> <label for="tag_subscription_is_public">
<%= check_box "tag_subscription", "is_public" %> <%= check_box "tag_subscription", "is_public" %>

View File

@@ -5,7 +5,7 @@
<th><label for="search_name_matches">Name</label></th> <th><label for="search_name_matches">Name</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= text_field "search", "name_matches" %> <%= text_field "search", "name_matches", :value => params[:search][:name_matches] %>
<span class="hint">Use * for wildcard</span> <span class="hint">Use * for wildcard</span>
</div> </div>
</td> </td>
@@ -15,7 +15,7 @@
<th><label for="search_category">Category</label></th> <th><label for="search_category">Category</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= select "search", "category", [""] + Danbooru.config.canonical_tag_category_mapping.to_a %> <%= select "search", "category", [""] + Danbooru.config.canonical_tag_category_mapping.to_a, :selected => params[:search][:category] %>
</div> </div>
</td> </td>
</tr> </tr>
@@ -24,7 +24,7 @@
<th><label for="search_sort">Sort</label></th> <th><label for="search_sort">Sort</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= select "search", "sort", %w(count date name) %> <%= select "search", "sort", %w(count date name), :selected => params[:search][:sort] %>
</div> </div>
</td> </td>
</tr> </tr>
@@ -33,7 +33,7 @@
<th><label for="search_hide_empty">Hide Empty</label></th> <th><label for="search_hide_empty">Hide Empty</label></th>
<td> <td>
<div class="input"> <div class="input">
<%= select "search", "hide_empty", ["yes", "no"] %> <%= select "search", "hide_empty", ["yes", "no"], :selected => params[:search][:hide_empty] %>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -8,6 +8,7 @@
<li><%= link_to "Help", wiki_pages_path(:search => {:title => "help:tags"}) %></li> <li><%= link_to "Help", wiki_pages_path(:search => {:title => "help:tags"}) %></li>
<% if @tag %> <% if @tag %>
<li>|</li> <li>|</li>
<li><%= link_to "Posts (#{Post.fast_count(@tag.name)})", posts_path(:tags => @tag.name) %></li>
<li><%= link_to "Edit", edit_tag_path(@tag) %></li> <li><%= link_to "Edit", edit_tag_path(@tag) %></li>
<% if @tag.post_count < 1_000 %> <% if @tag.post_count < 1_000 %>
<li><%= link_to "Fix", new_tag_correction_path(:tag_id => @tag.id) %></li> <li><%= link_to "Fix", new_tag_correction_path(:tag_id => @tag.id) %></li>

View File

@@ -3,9 +3,18 @@
<h1>Search User Feedbacks</h1> <h1>Search User Feedbacks</h1>
<%= form_tag(user_feedbacks_path, :method => :get, :class => "simple_form") do %> <%= form_tag(user_feedbacks_path, :method => :get, :class => "simple_form") do %>
<%= search_field "user_name", :label => "User" %> <div class="input">
<%= search_field "creator_name", :label => "Creator" %> <%= search_field "user_name", :label => "User" %>
<%= submit_tag "Search" %>
<%= search_field "creator_name", :label => "Creator" %>
<label for="search_category">Category</label>
<%= select "search", "category", %w(positive negative neutral), :include_blank => true %>
</div>
<div class="input">
<%= submit_tag "Search" %>
</div>
<% end %> <% end %>
</div> </div>
</div> </div>

View File

@@ -1,9 +1,9 @@
<div id="c-user-feedbacks"> <div id="c-user-feedbacks">
<div id="a-show"> <div id="a-show">
<h1>User Feedback For <%= @user_feedback.user_name %></h1> <h1>User Feedback For <%= link_to_user @user_feedback.user %></h1>
<ul> <ul>
<li><strong>Creator</strong> <%= @user_feedback.creator.name %></li> <li><strong>Creator</strong> <%= link_to_user @user_feedback.creator %></li>
<li><strong>Date</strong> <%= @user_feedback.created_at %></li> <li><strong>Date</strong> <%= @user_feedback.created_at %></li>
<li><strong>Category</strong> <%= @user_feedback.category %></li> <li><strong>Category</strong> <%= @user_feedback.category %></li>
<li><strong>Message</strong> <%= format_text @user_feedback.body %></li> <li><strong>Message</strong> <%= format_text @user_feedback.body %></li>

View File

@@ -1,5 +1,5 @@
<div class="ui-corner-all ui-state-error" id="ban-notice"> <div class="ui-corner-all ui-state-error" id="ban-notice">
<h1>Your account has been temporarily banned</h1> <h1>Your account has been temporarily banned</h1>
<p>Reason: <%= CurrentUser.user.ban.reason %></p> <p>Reason: <%= CurrentUser.user.recent_ban.reason %></p>
<p>Your ban will expire in <%= time_ago_in_words(CurrentUser.user.ban.expires_at) %></p> <p>Your ban will expire in <%= time_ago_in_words(CurrentUser.user.recent_ban.expires_at) %></p>
</div> </div>

View File

@@ -16,7 +16,7 @@
<li><%= link_to "Edit subscriptions", tag_subscriptions_path %></li> <li><%= link_to "Edit subscriptions", tag_subscriptions_path %></li>
<% end %> <% end %>
<li><%= link_to "Profile", user_path(CurrentUser.user) %></li> <li><%= link_to "Profile", user_path(CurrentUser.user) %></li>
<li><%= link_to "Messages #{CurrentUser.dmail_count}", dmails_path(:search => {:owner_id => CurrentUser.id, :to_id => CurrentUser.id}, :folder => "received") %></li> <li><%= link_to "Messages #{CurrentUser.dmail_count}", dmails_current_folder_path %></li>
<% else %> <% else %>
<li><%= link_to "Send message", new_dmail_path(:dmail => {:to_id => @user.id}) %></li> <li><%= link_to "Send message", new_dmail_path(:dmail => {:to_id => @user.id}) %></li>
<% end %> <% end %>
@@ -28,7 +28,7 @@
<% if CurrentUser.is_moderator? %> <% if CurrentUser.is_moderator? %>
<li><%= link_to "Promote", edit_admin_user_path(@user) %></li> <li><%= link_to "Promote", edit_admin_user_path(@user) %></li>
<% if @user.is_banned? %> <% if @user.is_banned? %>
<li><%= link_to "Unban", ban_path(@user.ban) %></li> <li><%= link_to "Unban", ban_path(@user.recent_ban) %></li>
<% else %> <% else %>
<li><%= link_to "Ban", new_ban_path(:ban => {:user_id => @user.id}) %></li> <li><%= link_to "Ban", new_ban_path(:ban => {:user_id => @user.id}) %></li>
<% end %> <% end %>

View File

@@ -11,3 +11,7 @@
</div> </div>
<%= render "wiki_pages/secondary_links" %> <%= render "wiki_pages/secondary_links" %>
<% content_for(:page_title) do %>
Wiki Page Versions Comparison - <%= @thispage.pretty_title %> - <%= Danbooru.config.app_name %>
<% end %>

View File

@@ -13,28 +13,9 @@
<%= render "form" %> <%= render "form" %>
<% if @wiki_page.presenter.antecedent_tag_alias %> <%= wiki_page_alias_and_implication_list(@wiki_page)%>
<p class="hint">This tag has been aliased to <%= link_to @wiki_page.presenter.antecedent_tag_alias.consequent_name, show_or_new_wiki_pages_path(:title => @wiki_page.presenter.antecedent_tag_alias.consequent_name) %>.</p>
<% end %>
<% if @wiki_page.presenter.consequent_tag_aliases.any? %> <%= wiki_page_post_previews(@wiki_page) %>
<p class="hint">The following tags are aliased to this tag: <%= raw @wiki_page.presenter.consequent_tag_aliases.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ") %>.</p>
<% end %>
<% if @wiki_page.presenter.antecedent_tag_implications.any? %>
<p class="hint">This tag has been implicated to <%= raw @wiki_page.presenter.antecedent_tag_implications.map {|x| link_to(x.consequent_name, show_or_new_wiki_pages_path(:title => x.consequent_name))}.join(", ") %>.</p>
<% end %>
<% if @wiki_page.presenter.consequent_tag_implications.any? %>
<p class="hint">The following tags are implicated to this tag: <%= raw @wiki_page.presenter.consequent_tag_implications.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ") %>.</p>
<% end %>
<div id="wiki-page-posts">
<% if Post.fast_count(@wiki_page.title) > 0 %>
<h2>Posts</h2>
<% end %>
<%= @wiki_page.post_set.presenter.post_previews_html(self) %>
</div>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@@ -15,29 +15,10 @@
<div id="wiki-page-body" class="prose"> <div id="wiki-page-body" class="prose">
<%= format_text(@wiki_page.body) %> <%= format_text(@wiki_page.body) %>
<% if @wiki_page.presenter.antecedent_tag_alias %> <%= wiki_page_alias_and_implication_list(@wiki_page) %>
<p class="hint">This tag has been aliased to <%= link_to @wiki_page.presenter.antecedent_tag_alias.consequent_name, show_or_new_wiki_pages_path(:title => @wiki_page.presenter.antecedent_tag_alias.consequent_name) %>.</p>
<% end %>
<% if @wiki_page.presenter.consequent_tag_aliases.any? %>
<p class="hint">The following tags are aliased to this tag: <%= raw @wiki_page.presenter.consequent_tag_aliases.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ") %>.</p>
<% end %>
<% if @wiki_page.presenter.antecedent_tag_implications.any? %>
<p class="hint">This tag has been implicated to <%= raw @wiki_page.presenter.antecedent_tag_implications.map {|x| link_to(x.consequent_name, show_or_new_wiki_pages_path(:title => x.consequent_name))}.join(", ") %>.</p>
<% end %>
<% if @wiki_page.presenter.consequent_tag_implications.any? %>
<p class="hint">The following tags are implicated to this tag: <%= raw @wiki_page.presenter.consequent_tag_implications.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ") %>.</p>
<% end %>
</div> </div>
<div id="wiki-page-posts"> <%= wiki_page_post_previews(@wiki_page) %>
<% if Post.fast_count(@wiki_page.title) > 0 %>
<h2>Posts</h2>
<% end %>
<%= @wiki_page.post_set.presenter.post_previews_html(self) %>
</div>
</section> </section>
</div> </div>
</div> </div>

Some files were not shown because too many files have changed in this diff Show More