Merge remote-tracking branch 'upstream/master'
This commit is contained in:
7
Gemfile
7
Gemfile
@@ -8,7 +8,11 @@ group :test do
|
|||||||
gem "simplecov", :require => false
|
gem "simplecov", :require => false
|
||||||
end
|
end
|
||||||
|
|
||||||
gem "rails", "3.1.0.rc1"
|
group :assets do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
gem "rails", "3.1.0.rc5"
|
||||||
gem "pg"
|
gem "pg"
|
||||||
gem "memcache-client", :require => "memcache"
|
gem "memcache-client", :require => "memcache"
|
||||||
gem "imagesize", :require => "image_size"
|
gem "imagesize", :require => "image_size"
|
||||||
@@ -20,3 +24,4 @@ gem "mechanize"
|
|||||||
gem "nokogiri"
|
gem "nokogiri"
|
||||||
gem "meta_search", :git => "git://github.com/ernie/meta_search.git"
|
gem "meta_search", :git => "git://github.com/ernie/meta_search.git"
|
||||||
gem "silent-postgres"
|
gem "silent-postgres"
|
||||||
|
gem "whenever", :require => false
|
||||||
95
Gemfile.lock
95
Gemfile.lock
@@ -16,37 +16,37 @@ GIT
|
|||||||
GEM
|
GEM
|
||||||
remote: http://gemcutter.org/
|
remote: http://gemcutter.org/
|
||||||
specs:
|
specs:
|
||||||
actionmailer (3.1.0.rc1)
|
aaronh-chronic (0.3.9)
|
||||||
actionpack (= 3.1.0.rc1)
|
actionmailer (3.1.0.rc5)
|
||||||
|
actionpack (= 3.1.0.rc5)
|
||||||
mail (~> 2.3.0)
|
mail (~> 2.3.0)
|
||||||
actionpack (3.1.0.rc1)
|
actionpack (3.1.0.rc5)
|
||||||
activemodel (= 3.1.0.rc1)
|
activemodel (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
builder (~> 3.0.0)
|
builder (~> 3.0.0)
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
i18n (~> 0.6.0beta1)
|
i18n (~> 0.6)
|
||||||
rack (~> 1.3.0.beta2)
|
rack (~> 1.3.1)
|
||||||
rack-cache (~> 1.0.1)
|
rack-cache (~> 1.0.2)
|
||||||
rack-mount (~> 0.8.1)
|
rack-mount (~> 0.8.1)
|
||||||
rack-test (~> 0.6.0)
|
rack-test (~> 0.6.0)
|
||||||
sprockets (~> 2.0.0.beta.5)
|
sprockets (~> 2.0.0.beta.12)
|
||||||
tzinfo (~> 0.3.27)
|
activemodel (3.1.0.rc5)
|
||||||
activemodel (3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
|
||||||
bcrypt-ruby (~> 2.1.4)
|
bcrypt-ruby (~> 2.1.4)
|
||||||
builder (~> 3.0.0)
|
builder (~> 3.0.0)
|
||||||
i18n (~> 0.6.0beta1)
|
i18n (~> 0.6)
|
||||||
activerecord (3.1.0.rc1)
|
activerecord (3.1.0.rc5)
|
||||||
activemodel (= 3.1.0.rc1)
|
activemodel (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
arel (~> 2.1.1)
|
arel (~> 2.1.4)
|
||||||
tzinfo (~> 0.3.27)
|
tzinfo (~> 0.3.29)
|
||||||
activeresource (3.1.0.rc1)
|
activeresource (3.1.0.rc5)
|
||||||
activemodel (= 3.1.0.rc1)
|
activemodel (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
activesupport (3.1.0.rc1)
|
activesupport (3.1.0.rc5)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
arel (2.1.3)
|
arel (2.1.4)
|
||||||
bcrypt-ruby (2.1.4)
|
bcrypt-ruby (2.1.4)
|
||||||
builder (3.0.0)
|
builder (3.0.0)
|
||||||
daemons (1.1.4)
|
daemons (1.1.4)
|
||||||
@@ -54,9 +54,9 @@ GEM
|
|||||||
activesupport (~> 3.0)
|
activesupport (~> 3.0)
|
||||||
daemons
|
daemons
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
factory_girl (1.3.3)
|
factory_girl (2.0.3)
|
||||||
haml (3.1.2)
|
haml (3.1.2)
|
||||||
hike (1.1.0)
|
hike (1.2.0)
|
||||||
i18n (0.6.0)
|
i18n (0.6.0)
|
||||||
imagesize (0.1.1)
|
imagesize (0.1.1)
|
||||||
mail (2.3.0)
|
mail (2.3.0)
|
||||||
@@ -64,10 +64,10 @@ GEM
|
|||||||
mime-types (~> 1.16)
|
mime-types (~> 1.16)
|
||||||
treetop (~> 1.4.8)
|
treetop (~> 1.4.8)
|
||||||
mechanize (2.0.1)
|
mechanize (2.0.1)
|
||||||
net-http-digest_auth (~> 1.1, >= 1.1.1)
|
net-http-digest_auth (>= 1.1.1, ~> 1.1)
|
||||||
net-http-persistent (~> 1.8)
|
net-http-persistent (~> 1.8)
|
||||||
nokogiri (~> 1.4)
|
nokogiri (~> 1.4)
|
||||||
webrobots (~> 0.0, >= 0.0.9)
|
webrobots (>= 0.0.9, ~> 0.0)
|
||||||
memcache-client (1.8.5)
|
memcache-client (1.8.5)
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
mocha (0.9.12)
|
mocha (0.9.12)
|
||||||
@@ -76,31 +76,33 @@ GEM
|
|||||||
net-http-persistent (1.8)
|
net-http-persistent (1.8)
|
||||||
nokogiri (1.5.0)
|
nokogiri (1.5.0)
|
||||||
pg (0.11.0)
|
pg (0.11.0)
|
||||||
polyglot (0.3.1)
|
polyglot (0.3.2)
|
||||||
rack (1.3.1)
|
rack (1.3.2)
|
||||||
rack-cache (1.0.2)
|
rack-cache (1.0.2)
|
||||||
rack (>= 0.4)
|
rack (>= 0.4)
|
||||||
rack-mount (0.8.1)
|
rack-mount (0.8.1)
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-ssl (1.3.2)
|
rack-ssl (1.3.2)
|
||||||
rack
|
rack
|
||||||
rack-test (0.6.0)
|
rack-test (0.6.1)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rails (3.1.0.rc1)
|
rails (3.1.0.rc5)
|
||||||
actionmailer (= 3.1.0.rc1)
|
actionmailer (= 3.1.0.rc5)
|
||||||
actionpack (= 3.1.0.rc1)
|
actionpack (= 3.1.0.rc5)
|
||||||
activerecord (= 3.1.0.rc1)
|
activerecord (= 3.1.0.rc5)
|
||||||
activeresource (= 3.1.0.rc1)
|
activeresource (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
bundler (~> 1.0)
|
bundler (~> 1.0)
|
||||||
railties (= 3.1.0.rc1)
|
railties (= 3.1.0.rc5)
|
||||||
railties (3.1.0.rc1)
|
railties (3.1.0.rc5)
|
||||||
actionpack (= 3.1.0.rc1)
|
actionpack (= 3.1.0.rc5)
|
||||||
activesupport (= 3.1.0.rc1)
|
activesupport (= 3.1.0.rc5)
|
||||||
rack-ssl (~> 1.3.2)
|
rack-ssl (~> 1.3.2)
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
|
rdoc (~> 3.4)
|
||||||
thor (~> 0.14.6)
|
thor (~> 0.14.6)
|
||||||
rake (0.9.2)
|
rake (0.9.2)
|
||||||
|
rdoc (3.9.1)
|
||||||
shoulda (2.11.3)
|
shoulda (2.11.3)
|
||||||
silent-postgres (0.0.8)
|
silent-postgres (0.0.8)
|
||||||
simple_form (1.4.2)
|
simple_form (1.4.2)
|
||||||
@@ -109,8 +111,8 @@ GEM
|
|||||||
simplecov (0.4.2)
|
simplecov (0.4.2)
|
||||||
simplecov-html (~> 0.4.4)
|
simplecov-html (~> 0.4.4)
|
||||||
simplecov-html (0.4.5)
|
simplecov-html (0.4.5)
|
||||||
sprockets (2.0.0.beta.10)
|
sprockets (2.0.0.beta.13)
|
||||||
hike (~> 1.0)
|
hike (~> 1.2)
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
tilt (!= 1.3.0, ~> 1.1)
|
tilt (!= 1.3.0, ~> 1.1)
|
||||||
super_exception_notifier (3.0.13)
|
super_exception_notifier (3.0.13)
|
||||||
@@ -118,11 +120,15 @@ GEM
|
|||||||
rake
|
rake
|
||||||
thor (0.14.6)
|
thor (0.14.6)
|
||||||
tilt (1.3.2)
|
tilt (1.3.2)
|
||||||
treetop (1.4.9)
|
treetop (1.4.10)
|
||||||
|
polyglot
|
||||||
polyglot (>= 0.3.1)
|
polyglot (>= 0.3.1)
|
||||||
tzinfo (0.3.29)
|
tzinfo (0.3.29)
|
||||||
webrobots (0.0.10)
|
webrobots (0.0.10)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
|
whenever (0.6.8)
|
||||||
|
aaronh-chronic (>= 0.3.9)
|
||||||
|
activesupport (>= 2.3.4)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@@ -139,9 +145,10 @@ DEPENDENCIES
|
|||||||
mocha
|
mocha
|
||||||
nokogiri
|
nokogiri
|
||||||
pg
|
pg
|
||||||
rails (= 3.1.0.rc1)
|
rails (= 3.1.0.rc5)
|
||||||
shoulda
|
shoulda
|
||||||
silent-postgres
|
silent-postgres
|
||||||
simple_form
|
simple_form
|
||||||
simplecov
|
simplecov
|
||||||
super_exception_notifier
|
super_exception_notifier
|
||||||
|
whenever
|
||||||
|
|||||||
118
app/assets/javascripts/blacklists.js
Normal file
118
app/assets/javascripts/blacklists.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
(function() {
|
||||||
|
Danbooru.Blacklist = {};
|
||||||
|
|
||||||
|
Danbooru.Blacklist.blacklists = [];
|
||||||
|
|
||||||
|
Danbooru.Blacklist.parse_entries = function() {
|
||||||
|
var entries = (Danbooru.meta("blacklisted-tags") || "").replace(/(rating:[qes])\w+/, "$1").split(/,/);
|
||||||
|
$.each(entries, function(i, tags) {
|
||||||
|
var blacklist = {
|
||||||
|
"tags": tags,
|
||||||
|
"require": [],
|
||||||
|
"exclude": [],
|
||||||
|
"disabled": false,
|
||||||
|
"hits": 0
|
||||||
|
};
|
||||||
|
var matches = tags.match(/\S+/g) || [];
|
||||||
|
$.each(matches, function(i, tag) {
|
||||||
|
if (tag.charAt(0) === '-') {
|
||||||
|
blacklist.exclude.push(tag.slice(1));
|
||||||
|
} else {
|
||||||
|
blacklist.require.push(tag);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Danbooru.Blacklist.blacklists.push(blacklist);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.toggle = function(e) {
|
||||||
|
$(".blacklisted").each(function(i, element) {
|
||||||
|
var $element = $(element);
|
||||||
|
if ($element.hasClass("blacklisted-active")) {
|
||||||
|
$element.removeClass("blacklisted-active");
|
||||||
|
} else {
|
||||||
|
$element.addClass("blacklisted-active");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.update_sidebar = function() {
|
||||||
|
$.each(this.blacklists, function(i, blacklist) {
|
||||||
|
if (blacklist.hits === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = $("<li/>");
|
||||||
|
var link = $("<a/>");
|
||||||
|
var count = $("<span/>");
|
||||||
|
link.html(blacklist.tags);
|
||||||
|
link.click(Danbooru.Blacklist.toggle);
|
||||||
|
count.html(blacklist.hits);
|
||||||
|
item.append(link);
|
||||||
|
item.append(" ");
|
||||||
|
item.append(count);
|
||||||
|
$("#blacklist-list").append(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#blacklist-box").show();
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.apply = function() {
|
||||||
|
$.each(this.blacklists, function(i, blacklist) {
|
||||||
|
blacklist.hits = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
$.each(this.posts(), function(i, post) {
|
||||||
|
$.each(Danbooru.Blacklist.blacklists, function(i, blacklist) {
|
||||||
|
if (Danbooru.Blacklist.post_match(post, blacklist)) {
|
||||||
|
Danbooru.Blacklist.post_hide(post);
|
||||||
|
blacklist.hits += 1;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.posts = function() {
|
||||||
|
return $("article.post-preview");
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.post_match = function(post, blacklist) {
|
||||||
|
var $post = $(post);
|
||||||
|
var tags = $post.data("tags").match(/\S+/g) || [];
|
||||||
|
tags.push("rating:" + $post.data("rating"));
|
||||||
|
tags.push("uploader:" + $post.data("uploader"));
|
||||||
|
|
||||||
|
if (blacklist.require.length > 0 || blacklist.exclude.length > 0) {
|
||||||
|
if (blacklist.require.length === 0 || Danbooru.is_subset(tags, blacklist.require)) {
|
||||||
|
if (blacklist.exclude.length === 0 || (!Danbooru.is_subset(tags, blacklist.exclude))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.post_hide = function(post) {
|
||||||
|
var $post = $(post);
|
||||||
|
$post.addClass("blacklisted").addClass("blacklisted-active");
|
||||||
|
}
|
||||||
|
|
||||||
|
Danbooru.Blacklist.initialize = function() {
|
||||||
|
Danbooru.Blacklist.parse_entries();
|
||||||
|
if (Danbooru.Blacklist.apply() > 0) {
|
||||||
|
Danbooru.Blacklist.update_sidebar();
|
||||||
|
} else {
|
||||||
|
$("#blacklist-box").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
Danbooru.Blacklist.initialize();
|
||||||
|
});
|
||||||
@@ -51,15 +51,23 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.get("hide-news-ticker") == "1") {
|
||||||
|
$("#news-ticker").hide();
|
||||||
|
} else {
|
||||||
|
$("#close-news-ticker-link").click(function(e) {
|
||||||
|
$("#news-ticker").hide();
|
||||||
|
Danbooru.Cookie.put("hide-news-ticker", "1", 1);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (this.get("hide-upgrade-account") != "1") {
|
if (this.get("hide-upgrade-account") != "1") {
|
||||||
if ($("upgrade-account")) {
|
$("#upgrade-account").show();
|
||||||
$("upgrade-account").show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(function() {
|
||||||
Danbooru.Cookie.initialize();
|
Danbooru.Cookie.initialize();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,16 @@
|
|||||||
Danbooru.ajax_stop = function(target) {
|
Danbooru.ajax_stop = function(target) {
|
||||||
$(target).next("img.wait").remove();
|
$(target).next("img.wait").remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Danbooru.is_subset = function(array, subarray) {
|
||||||
|
var all = true;
|
||||||
|
|
||||||
|
$.each(subarray, function(i, val) {
|
||||||
|
if ($.inArray(val, array) === -1) {
|
||||||
|
all = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return all;
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ div#page {
|
|||||||
width: 75%;
|
width: 75%;
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 2em;
|
margin-left: 2em;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,6 +627,10 @@ article.post-preview {
|
|||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article.post-preview.blacklisted-active {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
div#c-posts {
|
div#c-posts {
|
||||||
div.notice {
|
div.notice {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
@@ -651,6 +656,23 @@ div#c-posts {
|
|||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aside#sidebar > section#blacklist-box ul {
|
||||||
|
margin-left: 1em;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $link_color;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: $h3_size;
|
font-size: $h3_size;
|
||||||
}
|
}
|
||||||
@@ -693,6 +715,9 @@ div#c-posts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#c-explore-posts {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** Post Histories ***/
|
/*** Post Histories ***/
|
||||||
div.post_histories {
|
div.post_histories {
|
||||||
@@ -1046,3 +1071,40 @@ div#moderator-dashboard {
|
|||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*** page footer ***/
|
||||||
|
footer#page-footer {
|
||||||
|
clear: both;
|
||||||
|
margin: 1em;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 1em;
|
||||||
|
border-top: 2px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** news ticker ***/
|
||||||
|
|
||||||
|
div#news-ticker {
|
||||||
|
padding: 5px;
|
||||||
|
background: #EEE;
|
||||||
|
border-bottom: 2px solid #666;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.8em;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
float: left;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
float: left;
|
||||||
|
margin: 0 2em 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a#close-news-ticker-link {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
module Admin
|
|
||||||
class PostsController
|
|
||||||
def edit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
class Admin::UsersController < ApplicationController
|
|
||||||
def edit
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
end
|
|
||||||
end
|
|
||||||
11
app/controllers/explore/posts_controller.rb
Normal file
11
app/controllers/explore/posts_controller.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module Explore
|
||||||
|
class PostsController < ApplicationController
|
||||||
|
respond_to :html, :xml, :json
|
||||||
|
|
||||||
|
def popular
|
||||||
|
@post_set = PostSets::Popular.new(params[:date], params[:scale])
|
||||||
|
@posts = @post_set.posts
|
||||||
|
respond_with(@posts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
19
app/controllers/moderator/tags_controller.rb
Normal file
19
app/controllers/moderator/tags_controller.rb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
module Moderator
|
||||||
|
class TagsController < ApplicationController
|
||||||
|
before_filter :moderator_only
|
||||||
|
rescue_from TagBatchChange::Error, :with => :error
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
tag_batch_change = TagBatchChange.new(params[:tag][:predicate], params[:tag][:consequent])
|
||||||
|
tag_batch_change.execute
|
||||||
|
redirect_to edit_moderator_tag_path, :notice => "Posts updated"
|
||||||
|
end
|
||||||
|
|
||||||
|
def error
|
||||||
|
redirect_to edit_moderator_tag_path, :notice => "Error"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -15,6 +15,7 @@ class TagAliasesController < ApplicationController
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
@tag_alias = TagAlias.create(params[:tag_alias])
|
@tag_alias = TagAlias.create(params[:tag_alias])
|
||||||
|
@tag_alias.delay.process!
|
||||||
respond_with(@tag_alias, :location => tag_aliases_path(:search => {:id_eq => @tag_alias.id}))
|
respond_with(@tag_alias, :location => tag_aliases_path(:search => {:id_eq => @tag_alias.id}))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class TagImplicationsController < ApplicationController
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
@tag_implication = TagImplication.create(params[:tag_implication])
|
@tag_implication = TagImplication.create(params[:tag_implication])
|
||||||
|
@tag_implication.delay.process!
|
||||||
respond_with(@tag_implication, :location => tag_implications_path(:search => {:id_eq => @tag_implication.id}))
|
respond_with(@tag_implication, :location => tag_implications_path(:search => {:id_eq => @tag_implication.id}))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
24
app/logical/moderator/tag_batch_change.rb
Normal file
24
app/logical/moderator/tag_batch_change.rb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
module Moderator
|
||||||
|
class TagBatchChange
|
||||||
|
class Error < Exception ; end
|
||||||
|
|
||||||
|
attr_reader :predicate, :consequent
|
||||||
|
|
||||||
|
def initialize(predicate, consequent)
|
||||||
|
@predicate = predicate
|
||||||
|
@consequent = consequent
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
raise Error.new("Predicate is missing") if predicate.blank?
|
||||||
|
|
||||||
|
normalized_predicate = TagAlias.to_aliased(::Tag.scan_tags(predicate))
|
||||||
|
normalized_consequent = TagAlias.to_aliased(::Tag.scan_tags(consequent))
|
||||||
|
|
||||||
|
::Post.tag_match(predicate).each do |post|
|
||||||
|
tags = (post.tag_array - normalized_predicate + normalized_consequent).join(" ")
|
||||||
|
post.update_attributes(:tag_string => tags)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,7 +4,7 @@ class PixivProxy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.get(url)
|
def self.get(url)
|
||||||
if url =~ /\/(\d+)(_m)?\.(jpg|jpeg|png|gif)/i
|
if url =~ /\/(\d+)(_m|_p\d+)?\.(jpg|jpeg|png|gif)/i
|
||||||
url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=#{$1}"
|
url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=#{$1}"
|
||||||
get_single(url)
|
get_single(url)
|
||||||
elsif url =~ /member_illust\.php/ && url =~ /illust_id=/
|
elsif url =~ /member_illust\.php/ && url =~ /illust_id=/
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
module PostSets
|
module PostSets
|
||||||
class Artist < Post
|
class Artist < PostSets::Post
|
||||||
attr_reader :artist
|
attr_reader :artist
|
||||||
|
|
||||||
def initialize(artist)
|
def initialize(artist)
|
||||||
super(:tags => artist.name)
|
super(artist.name)
|
||||||
@artist = artist
|
@artist = artist
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ module PostSets
|
|||||||
end
|
end
|
||||||
|
|
||||||
def artist
|
def artist
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_single_tag?
|
def is_single_tag?
|
||||||
|
|||||||
48
app/logical/post_sets/popular.rb
Normal file
48
app/logical/post_sets/popular.rb
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
module PostSets
|
||||||
|
class Popular < Base
|
||||||
|
attr_reader :date, :scale
|
||||||
|
|
||||||
|
def initialize(date, scale)
|
||||||
|
@date = date.blank? ? Date.today : date.to_date
|
||||||
|
@scale = scale
|
||||||
|
end
|
||||||
|
|
||||||
|
def posts
|
||||||
|
::Post.where("created_at between ? and ?", min_date, max_date + 1).order("score desc").limit(limit)
|
||||||
|
end
|
||||||
|
|
||||||
|
def limit
|
||||||
|
25
|
||||||
|
end
|
||||||
|
|
||||||
|
def min_date
|
||||||
|
case scale
|
||||||
|
when "week"
|
||||||
|
date.beginning_of_week
|
||||||
|
|
||||||
|
when "month"
|
||||||
|
date.beginning_of_month
|
||||||
|
|
||||||
|
else
|
||||||
|
date
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def max_date
|
||||||
|
case scale
|
||||||
|
when "week"
|
||||||
|
date.end_of_week
|
||||||
|
|
||||||
|
when "month"
|
||||||
|
date.end_of_month
|
||||||
|
|
||||||
|
else
|
||||||
|
date
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def presenter
|
||||||
|
::PostSetPresenters::Popular.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -13,6 +13,7 @@ class Comment < ActiveRecord::Base
|
|||||||
scope :body_matches, lambda {|query| where("body_index @@ plainto_tsquery(?)", query).order("comments.id DESC")}
|
scope :body_matches, lambda {|query| where("body_index @@ plainto_tsquery(?)", query).order("comments.id DESC")}
|
||||||
scope :hidden, lambda {|user| where("score < ?", user.comment_threshold)}
|
scope :hidden, lambda {|user| where("score < ?", user.comment_threshold)}
|
||||||
scope :post_tag_match, lambda {|query| joins(:post).where("posts.tag_index @@ to_tsquery('danbooru', ?)", query)}
|
scope :post_tag_match, lambda {|query| joins(:post).where("posts.tag_index @@ to_tsquery('danbooru', ?)", query)}
|
||||||
|
scope :for_user, lambda {|user_id| where("creator_id = ?", user_id)}
|
||||||
|
|
||||||
search_methods :body_matches, :post_tag_match
|
search_methods :body_matches, :post_tag_match
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
class Favorite < ActiveRecord::Base
|
class Favorite < ActiveRecord::Base
|
||||||
belongs_to :post
|
belongs_to :post
|
||||||
scope :for_user, lambda {|user_id| where("user_id = ?", user_id)}
|
scope :for_user, lambda {|user_id| where("user_id = #{user_id}")}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class ForumPost < ActiveRecord::Base
|
|||||||
validates_presence_of :body, :creator_id
|
validates_presence_of :body, :creator_id
|
||||||
validate :validate_topic_is_unlocked
|
validate :validate_topic_is_unlocked
|
||||||
scope :body_matches, lambda {|body| where(["text_index @@ plainto_tsquery(?)", body])}
|
scope :body_matches, lambda {|body| where(["text_index @@ plainto_tsquery(?)", body])}
|
||||||
|
scope :for_user, lambda {|user_id| where("creator_id = ?", user_id)}
|
||||||
search_methods :body_matches
|
search_methods :body_matches
|
||||||
|
|
||||||
def self.new_reply(params)
|
def self.new_reply(params)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class NoteVersion < ActiveRecord::Base
|
class NoteVersion < ActiveRecord::Base
|
||||||
before_validation :initialize_updater
|
before_validation :initialize_updater
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
|
scope :for_user, lambda {|user_id| where("updater_id = ?", user_id)}
|
||||||
|
|
||||||
def initialize_updater
|
def initialize_updater
|
||||||
self.updater_id = CurrentUser.id
|
self.updater_id = CurrentUser.id
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class PoolVersion < ActiveRecord::Base
|
|||||||
belongs_to :pool
|
belongs_to :pool
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
before_validation :initialize_updater
|
before_validation :initialize_updater
|
||||||
|
scope :for_user, lambda {|user_id| where("updater_id = ?", user_id)}
|
||||||
|
|
||||||
def initialize_updater
|
def initialize_updater
|
||||||
self.updater_id = CurrentUser.id
|
self.updater_id = CurrentUser.id
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class Post < ActiveRecord::Base
|
|||||||
scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
||||||
scope :hidden_from_moderation, lambda {where(["id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
scope :hidden_from_moderation, lambda {where(["id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
|
||||||
scope :tag_match, lambda {|query| Post.tag_match_helper(query)}
|
scope :tag_match, lambda {|query| Post.tag_match_helper(query)}
|
||||||
|
scope :exact_tag_match, lambda {|query| Post.exact_tag_match_helper(query)}
|
||||||
scope :positive, where("score > 1")
|
scope :positive, where("score > 1")
|
||||||
scope :negative, where("score < -1")
|
scope :negative, where("score < -1")
|
||||||
search_methods :tag_match
|
search_methods :tag_match
|
||||||
@@ -487,21 +488,30 @@ class Post < ActiveRecord::Base
|
|||||||
|
|
||||||
def add_tag_subscription_relation(subscriptions, relation)
|
def add_tag_subscription_relation(subscriptions, relation)
|
||||||
subscriptions.each do |subscription|
|
subscriptions.each do |subscription|
|
||||||
subscription =~ /^(.+?):(.+)$/
|
if subscription =~ /^(.+?):(.+)$/
|
||||||
user_name = $1 || subscription
|
user_name = $1
|
||||||
subscription_name = $2
|
subscription_name = $2
|
||||||
|
user = User.find_by_name(user_name)
|
||||||
user = User.find_by_name(user_name)
|
return relation if user.nil?
|
||||||
|
|
||||||
if user
|
|
||||||
post_ids = TagSubscription.find_post_ids(user.id, subscription_name)
|
post_ids = TagSubscription.find_post_ids(user.id, subscription_name)
|
||||||
relation = relation.where(["posts.id IN (?)", post_ids])
|
else
|
||||||
|
user = User.find_by_name(subscription)
|
||||||
|
return relation if user.nil?
|
||||||
|
post_ids = TagSubscription.find_post_ids(user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post_ids = [0] if post_ids.empty?
|
||||||
|
relation = relation.where(["posts.id IN (?)", post_ids])
|
||||||
end
|
end
|
||||||
|
|
||||||
relation
|
relation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def exact_tag_match_helper(q)
|
||||||
|
arel = Post.scoped
|
||||||
|
add_tag_string_search_relation({:related => [q].flatten, :include => [], :exclude => []}, arel)
|
||||||
|
end
|
||||||
|
|
||||||
def tag_match_helper(q)
|
def tag_match_helper(q)
|
||||||
unless q.is_a?(Hash)
|
unless q.is_a?(Hash)
|
||||||
q = Tag.parse_query(q)
|
q = Tag.parse_query(q)
|
||||||
@@ -576,6 +586,10 @@ class Post < ActiveRecord::Base
|
|||||||
relation = relation.where("posts.rating <> 'e'")
|
relation = relation.where("posts.rating <> 'e'")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if q[:order] == "rank"
|
||||||
|
relation = relation.where("p.score > 0 and p.created_at >= ?", 0, 3.days.ago)
|
||||||
|
end
|
||||||
|
|
||||||
case q[:order]
|
case q[:order]
|
||||||
when "id", "id_asc"
|
when "id", "id_asc"
|
||||||
relation = relation.order("posts.id")
|
relation = relation.order("posts.id")
|
||||||
@@ -609,6 +623,9 @@ class Post < ActiveRecord::Base
|
|||||||
when "filesize_asc"
|
when "filesize_asc"
|
||||||
relation = relation.order("posts.file_size")
|
relation = relation.order("posts.file_size")
|
||||||
|
|
||||||
|
when "rank"
|
||||||
|
sql << " ORDER BY log(3, p.score) + (extract(epoch from p.created_at) - extract(epoch from timestamp '2005-05-24')) / 45000 DESC"
|
||||||
|
|
||||||
else
|
else
|
||||||
relation = relation.order("posts.id DESC")
|
relation = relation.order("posts.id DESC")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ class PostVersion < ActiveRecord::Base
|
|||||||
belongs_to :post
|
belongs_to :post
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
before_validation :initialize_updater
|
before_validation :initialize_updater
|
||||||
|
scope :for_user, lambda {|user_id| where("updater_id = ?", user_id)}
|
||||||
|
|
||||||
def self.create_from_post(post)
|
def self.create_from_post(post)
|
||||||
if post.created_at == post.updated_at
|
if post.created_at == post.updated_at
|
||||||
|
|||||||
@@ -107,20 +107,6 @@ class Tag < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module UpdateMethods
|
|
||||||
def mass_edit(start_tags, result_tags, updater_id, updater_ip_addr)
|
|
||||||
updater = User.find(updater_id)
|
|
||||||
Post.tag_match(start_tags).each do |p|
|
|
||||||
start = TagAlias.to_aliased(scan_tags(start_tags))
|
|
||||||
result = TagAlias.to_aliased(scan_tags(result_tags))
|
|
||||||
tags = (p.tag_array - start + result).join(" ")
|
|
||||||
CurrentUser.scoped(updater, updater_ip_addr) do
|
|
||||||
p.update_attributes(:tag_string => tags)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module ParseMethods
|
module ParseMethods
|
||||||
def normalize(query)
|
def normalize(query)
|
||||||
query.to_s.downcase.strip
|
query.to_s.downcase.strip
|
||||||
@@ -323,12 +309,13 @@ class Tag < ActiveRecord::Base
|
|||||||
|
|
||||||
module RelationMethods
|
module RelationMethods
|
||||||
def update_related
|
def update_related
|
||||||
|
return unless should_update_related?
|
||||||
counts = RelatedTagCalculator.calculate_from_sample(Danbooru.config.post_sample_size, name)
|
counts = RelatedTagCalculator.calculate_from_sample(Danbooru.config.post_sample_size, name)
|
||||||
self.related_tags = RelatedTagCalculator.convert_hash_to_string(counts)
|
update_attributes(:related_tags => RelatedTagCalculator.convert_hash_to_string(counts), :related_tags_updated_at => Time.now)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_related_if_outdated
|
def update_related_if_outdated
|
||||||
updated_related if should_update_related?
|
delay.update_related if should_update_related?
|
||||||
end
|
end
|
||||||
|
|
||||||
def related_cache_expiry
|
def related_cache_expiry
|
||||||
@@ -345,7 +332,8 @@ class Tag < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def related_tag_array
|
def related_tag_array
|
||||||
related_tags.split(/ /).in_groups_of(2)
|
update_related_if_outdated
|
||||||
|
related_tags.to_s.split(/ /).in_groups_of(2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -367,7 +355,7 @@ class Tag < ActiveRecord::Base
|
|||||||
include CategoryMethods
|
include CategoryMethods
|
||||||
extend StatisticsMethods
|
extend StatisticsMethods
|
||||||
include NameMethods
|
include NameMethods
|
||||||
extend UpdateMethods
|
|
||||||
extend ParseMethods
|
extend ParseMethods
|
||||||
|
include RelationMethods
|
||||||
extend SuggestionMethods
|
extend SuggestionMethods
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
class TagAlias < ActiveRecord::Base
|
class TagAlias < ActiveRecord::Base
|
||||||
attr_accessor :creator_ip_addr
|
before_save :clear_all_cache
|
||||||
after_save :update_posts
|
|
||||||
after_save :clear_cache
|
|
||||||
after_save :clear_remote_cache
|
|
||||||
after_save :update_cache
|
after_save :update_cache
|
||||||
after_destroy :clear_cache
|
after_destroy :clear_all_cache
|
||||||
after_destroy :clear_remote_cache
|
|
||||||
before_validation :initialize_creator, :on => :create
|
before_validation :initialize_creator, :on => :create
|
||||||
validates_presence_of :creator_id
|
validates_presence_of :creator_id
|
||||||
validates_uniqueness_of :antecedent_name
|
validates_uniqueness_of :antecedent_name
|
||||||
@@ -25,8 +21,17 @@ class TagAlias < ActiveRecord::Base
|
|||||||
alias_hash.values.flatten.uniq
|
alias_hash.values.flatten.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def process!
|
||||||
|
update_column(:status, "processing")
|
||||||
|
update_posts
|
||||||
|
update_column(:status, "active")
|
||||||
|
rescue Exception => e
|
||||||
|
update_column(:status, "error: #{e}")
|
||||||
|
end
|
||||||
|
|
||||||
def initialize_creator
|
def initialize_creator
|
||||||
self.creator_id = CurrentUser.user.id
|
self.creator_id = CurrentUser.user.id
|
||||||
|
self.creator_ip_addr = CurrentUser.ip_addr
|
||||||
end
|
end
|
||||||
|
|
||||||
def antecedent_tag
|
def antecedent_tag
|
||||||
@@ -45,6 +50,11 @@ class TagAlias < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def clear_all_cache
|
||||||
|
clear_cache
|
||||||
|
clear_remote_cache
|
||||||
|
end
|
||||||
|
|
||||||
def clear_cache
|
def clear_cache
|
||||||
Cache.delete("ta:#{Cache.sanitize(antecedent_name)}")
|
Cache.delete("ta:#{Cache.sanitize(antecedent_name)}")
|
||||||
end
|
end
|
||||||
@@ -60,13 +70,15 @@ class TagAlias < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_posts
|
def update_posts
|
||||||
Post.tag_match(antecedent_name).find_each do |post|
|
Post.exact_tag_match(antecedent_name).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| )/, " #{consequent_name} ").strip
|
fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{consequent_name} ").strip
|
||||||
|
|
||||||
post.update_attributes(
|
CurrentUser.scoped(creator, creator_ip_addr) do
|
||||||
:tag_string => fixed_tags
|
post.update_attributes(
|
||||||
)
|
:tag_string => fixed_tags
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,43 +1,19 @@
|
|||||||
class TagImplication < ActiveRecord::Base
|
class TagImplication < ActiveRecord::Base
|
||||||
before_save :clear_cache
|
|
||||||
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_save :update_cache
|
|
||||||
after_save :update_posts
|
|
||||||
after_destroy :clear_cache
|
|
||||||
after_destroy :clear_remote_cache
|
|
||||||
belongs_to :creator, :class_name => "User"
|
belongs_to :creator, :class_name => "User"
|
||||||
before_validation :initialize_creator, :on => :create
|
before_validation :initialize_creator, :on => :create
|
||||||
validates_presence_of :creator_id
|
validates_presence_of :creator_id
|
||||||
validates_uniqueness_of :antecedent_name, :scope => :consequent_name
|
validates_uniqueness_of :antecedent_name, :scope => :consequent_name
|
||||||
validate :absence_of_circular_relation
|
validate :absence_of_circular_relation
|
||||||
|
|
||||||
module CacheMethods
|
|
||||||
def clear_cache
|
|
||||||
Cache.delete("ti:#{Cache.sanitize(antecedent_name)}")
|
|
||||||
@descendants = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def clear_remote_cache
|
|
||||||
Danbooru.config.other_server_hosts.each do |server|
|
|
||||||
Net::HTTP.delete(URI.parse("http://#{server}/tag_implications/#{id}/cache"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_cache
|
|
||||||
descendant_names_array
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module DescendantMethods
|
module DescendantMethods
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
# assumes names are normalized
|
||||||
def with_descendants(names)
|
def with_descendants(names)
|
||||||
names + Cache.get_multi(names.flatten, "ti") do |name|
|
(names + where("antecedent_name in (?)", names).map(&:descendant_names_array)).flatten.uniq
|
||||||
([name] + where(["antecedent_name = ?", name]).all.map {|x| x.descendant_names_array}).flatten
|
|
||||||
end.values.flatten.uniq
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -55,9 +31,7 @@ class TagImplication < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def descendant_names_array
|
def descendant_names_array
|
||||||
Cache.get("ti:#{Cache.sanitize(antecedent_name)}") do
|
descendant_names.split(/ /)
|
||||||
descendant_names.split(/ /)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_descendant_names
|
def update_descendant_names
|
||||||
@@ -93,12 +67,20 @@ class TagImplication < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
include CacheMethods
|
|
||||||
include DescendantMethods
|
include DescendantMethods
|
||||||
include ParentMethods
|
include ParentMethods
|
||||||
|
|
||||||
def initialize_creator
|
def initialize_creator
|
||||||
self.creator_id = CurrentUser.user.id
|
self.creator_id = CurrentUser.user.id
|
||||||
|
self.creator_ip_addr = CurrentUser.ip_addr
|
||||||
|
end
|
||||||
|
|
||||||
|
def process!
|
||||||
|
update_column(:status, "processing")
|
||||||
|
update_posts
|
||||||
|
update_column(:status, "active")
|
||||||
|
rescue Exception => e
|
||||||
|
update_column(:status, "error: #{e}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def absence_of_circular_relation
|
def absence_of_circular_relation
|
||||||
@@ -110,12 +92,14 @@ class TagImplication < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_posts
|
def update_posts
|
||||||
Post.tag_match(antecedent_name).find_each do |post|
|
Post.exact_tag_match(antecedent_name).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
|
||||||
post.update_attributes(
|
CurrentUser.scoped(creator, creator_ip_addr) do
|
||||||
:tag_string => fixed_tags
|
post.update_attributes(
|
||||||
)
|
:tag_string => fixed_tags
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class UserFeedback < ActiveRecord::Base
|
|||||||
scope :positive, where("category = ?", "positive")
|
scope :positive, where("category = ?", "positive")
|
||||||
scope :neutral, where("category = ?", "neutral")
|
scope :neutral, where("category = ?", "neutral")
|
||||||
scope :negative, where("category = ?", "negative")
|
scope :negative, where("category = ?", "negative")
|
||||||
|
scope :for_user, lambda {|user_id| where("user_id = ?", user_id)}
|
||||||
|
|
||||||
def initialize_creator
|
def initialize_creator
|
||||||
self.creator_id = CurrentUser.id
|
self.creator_id = CurrentUser.id
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class WikiPageVersion < ActiveRecord::Base
|
class WikiPageVersion < ActiveRecord::Base
|
||||||
belongs_to :wiki_page
|
belongs_to :wiki_page
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
|
scope :for_user, lambda {|user_id| where("updater_id = ?", user_id)}
|
||||||
|
|
||||||
def updater_name
|
def updater_name
|
||||||
User.id_to_name(updater_id)
|
User.id_to_name(updater_id)
|
||||||
|
|||||||
21
app/presenters/post_set_presenters/base.rb
Normal file
21
app/presenters/post_set_presenters/base.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
module PostSetPresenters
|
||||||
|
class Base
|
||||||
|
def posts
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_previews_html(template)
|
||||||
|
html = ""
|
||||||
|
|
||||||
|
if posts.empty?
|
||||||
|
return template.render(:partial => "post_sets/blank")
|
||||||
|
end
|
||||||
|
|
||||||
|
posts.each do |post|
|
||||||
|
html << PostPresenter.preview(post)
|
||||||
|
end
|
||||||
|
|
||||||
|
html.html_safe
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
module PostSetPresenters
|
module PostSetPresenters
|
||||||
class Favorite
|
class Favorite < Base
|
||||||
attr_accessor :favorite_set, :tag_set_presenter
|
attr_accessor :favorite_set, :tag_set_presenter
|
||||||
delegate :favorites, :posts, :to => :favorite_set
|
delegate :favorites, :to => :favorite_set
|
||||||
|
|
||||||
def initialize(favorite_set)
|
def initialize(favorite_set)
|
||||||
@favorite_set = favorite_set
|
@favorite_set = favorite_set
|
||||||
@@ -16,18 +16,8 @@ module PostSetPresenters
|
|||||||
tag_set_presenter.tag_list_html(template)
|
tag_set_presenter.tag_list_html(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_previews_html(template)
|
def posts
|
||||||
html = ""
|
favorites.map(&:post)
|
||||||
|
|
||||||
if favorites.empty?
|
|
||||||
return template.render(:partial => "post_sets/blank")
|
|
||||||
end
|
|
||||||
|
|
||||||
favorites.each do |favorite|
|
|
||||||
html << PostPresenter.preview(favorite.post)
|
|
||||||
end
|
|
||||||
|
|
||||||
html.html_safe
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
module PostSetPresenters
|
module PostSetPresenters
|
||||||
class Pool
|
class Pool < Base
|
||||||
attr_reader :tag_set_presenter, :pool_set
|
attr_reader :tag_set_presenter, :post_set
|
||||||
|
delegate :posts, :to => :post_set
|
||||||
|
|
||||||
def initialize(pool_set)
|
def initialize(post_set)
|
||||||
@pool_set = pool_set
|
@post_set = post_set
|
||||||
@tag_set_presenter = TagSetPresenter.new(
|
@tag_set_presenter = TagSetPresenter.new(
|
||||||
RelatedTagCalculator.calculate_from_sample_to_array(
|
RelatedTagCalculator.calculate_from_sample_to_array(
|
||||||
pool_set.tag_string
|
post_set.tag_string
|
||||||
).map {|x| x[0]}
|
).map {|x| x[0]}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -14,19 +15,5 @@ module PostSetPresenters
|
|||||||
def tag_list_html(template)
|
def tag_list_html(template)
|
||||||
tag_set_presenter.tag_list_html(template)
|
tag_set_presenter.tag_list_html(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_previews_html(template)
|
|
||||||
html = ""
|
|
||||||
|
|
||||||
if pool_set.posts.empty?
|
|
||||||
return template.render(:partial => "post_sets/blank")
|
|
||||||
end
|
|
||||||
|
|
||||||
pool_set.posts.each do |post|
|
|
||||||
html << PostPresenter.preview(post)
|
|
||||||
end
|
|
||||||
|
|
||||||
html.html_safe
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
34
app/presenters/post_set_presenters/popular.rb
Normal file
34
app/presenters/post_set_presenters/popular.rb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
module PostSetPresenters
|
||||||
|
class Popular < Base
|
||||||
|
attr_accessor :post_set, :tag_set_presenter
|
||||||
|
delegate :posts, :date, :to => :post_set
|
||||||
|
|
||||||
|
def initialize(post_set)
|
||||||
|
@post_set = post_set
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_day
|
||||||
|
date - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_day
|
||||||
|
date + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_week
|
||||||
|
date - 7
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_week
|
||||||
|
date + 7
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_month
|
||||||
|
1.month.ago(date)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_month
|
||||||
|
1.month.since(date)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,36 +1,26 @@
|
|||||||
module PostSetPresenters
|
module PostSetPresenters
|
||||||
class Post
|
class Post < Base
|
||||||
attr_accessor :post_set, :tag_set_presenter
|
attr_accessor :post_set, :tag_set_presenter
|
||||||
|
delegate :posts, :to => :post_set
|
||||||
|
|
||||||
def initialize(post_set)
|
def initialize(post_set)
|
||||||
@post_set = post_set
|
@post_set = post_set
|
||||||
@tag_set_presenter = TagSetPresenter.new(
|
@tag_set_presenter = TagSetPresenter.new(related_tags)
|
||||||
RelatedTagCalculator.calculate_from_sample_to_array(
|
|
||||||
post_set.tag_string
|
|
||||||
).map {|x| x[0]}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def posts
|
def related_tags
|
||||||
post_set.posts
|
if post_set.is_single_tag?
|
||||||
|
tag = Tag.find_by_name(post_set.tag_string)
|
||||||
|
if tag
|
||||||
|
return tag.related_tag_array.map(&:first)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RelatedTagCalculator.calculate_from_sample_to_array(post_set.tag_string).map(&:first)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_list_html(template)
|
def tag_list_html(template)
|
||||||
tag_set_presenter.tag_list_html(template)
|
tag_set_presenter.tag_list_html(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_previews_html(template)
|
|
||||||
html = ""
|
|
||||||
|
|
||||||
if posts.empty?
|
|
||||||
return template.render(:partial => "post_sets/blank")
|
|
||||||
end
|
|
||||||
|
|
||||||
posts.each do |post|
|
|
||||||
html << PostPresenter.preview(post)
|
|
||||||
end
|
|
||||||
|
|
||||||
html.html_safe
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
107
app/presenters/user_presenter.rb
Normal file
107
app/presenters/user_presenter.rb
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
class UserPresenter
|
||||||
|
attr_reader :user
|
||||||
|
|
||||||
|
def initialize(user)
|
||||||
|
@user = user
|
||||||
|
end
|
||||||
|
|
||||||
|
def level
|
||||||
|
user.level_string
|
||||||
|
end
|
||||||
|
|
||||||
|
def ban_reason
|
||||||
|
if user.is_banned?
|
||||||
|
"#{user.ban.reason}; expires #{user.ban.expires_at}"
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_subscriptions(template)
|
||||||
|
user.subscriptions.map do |subscription|
|
||||||
|
template.link_to(subscription.name, template.tag_subscription_path(subscription))
|
||||||
|
end.join("; ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload_limit
|
||||||
|
deleted_count = Post.for_user(user.id).deleted.count
|
||||||
|
pending_count = Post.for_user(user.id).pending.count
|
||||||
|
approved_count = Post.where("is_flagged = false and is_pending = false and user_id = ?", user.id).count
|
||||||
|
|
||||||
|
if user.base_upload_limit
|
||||||
|
limit = user.base_upload_limit - pending_count
|
||||||
|
string = "base:#{user.base_upload_limit} - pending:#{pending_count}"
|
||||||
|
else
|
||||||
|
limit = 10 + (approved_count / 10) - (deleted_count / 4) - pending_count
|
||||||
|
string = "base:10 + approved:(#{approved_count} / 10) - deleted:(#{deleted_count}) / 4 - pending:#{pending_count}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if limit > 20
|
||||||
|
limit = 20
|
||||||
|
string += " = capped:20"
|
||||||
|
elsif limit < 0
|
||||||
|
limit = 0
|
||||||
|
string += " = capped:0"
|
||||||
|
else
|
||||||
|
string += " = #{limit}"
|
||||||
|
end
|
||||||
|
|
||||||
|
return string
|
||||||
|
end
|
||||||
|
|
||||||
|
def uploads(template)
|
||||||
|
template.link_to(Post.for_user(user.id).count, template.posts_path(:tags => "uploader:#{user.name}"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def deleted_uploads(template)
|
||||||
|
template.link_to(Post.for_user(user.id).deleted.count, template.posts_path(:tags => "status:deleted uploader:#{user.name}"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def favorites(template)
|
||||||
|
template.link_to(Favorite.for_user(user.id).count, template.favorites_path(:user_id => user.id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def comments(template)
|
||||||
|
template.link_to(Comment.for_user(user.id).count, template.comments_path(:search => {:creator_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_versions(template)
|
||||||
|
template.link_to(PostVersion.for_user(user.id).count, template.post_versions_path(:search => {:updater_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_versions(template)
|
||||||
|
template.link_to(NoteVersion.for_user(user.id).count, template.note_versions_path(:search => {:updater_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def wiki_page_versions(template)
|
||||||
|
template.link_to(WikiPageVersion.for_user(user.id).count, template.wiki_page_versions_path(:search => {:updater_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def forum_posts(template)
|
||||||
|
template.link_to(ForumPost.for_user(user.id).count, template.forum_posts_path(:search => {:creator_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def pool_versions(template)
|
||||||
|
template.link_to(PoolVersion.for_user(user.id).count, template.pool_versions_path(:search => {:updater_id_eq => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def inviter(template)
|
||||||
|
if user.inviter_id
|
||||||
|
template.link_to(user.inviter.name, template.user_path(user.inviter_id))
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def approvals(template)
|
||||||
|
template.link_to(Post.where("approver_id = ?", user.id).count, template.posts_path(:tags => "approver:#{user.name}"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def feedbacks(template)
|
||||||
|
positive = UserFeedback.for_user(user.id).positive.count
|
||||||
|
neutral = UserFeedback.for_user(user.id).neutral.count
|
||||||
|
negative = UserFeedback.for_user(user.id).negative.count
|
||||||
|
|
||||||
|
template.link_to("positive:#{positive} neutral:#{neutral} negative:#{negative}", user_feedbacks_path(:search => {:user_id_rq => user.id}))
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<% form_tag({:action => "mass_edit"}, :onsubmit => "return confirm('Are you sure you wish to perform this tag edit?')") do %>
|
|
||||||
<%= text_field_tag "start", params[:source], :size => 60 %>
|
|
||||||
<%= text_field_tag "result", params[:name], :size => 60 %>
|
|
||||||
<%= button_to_function "Preview", "$('preview').innerHTML = 'Loading...'; new Ajax.Updater('preview', '#{url_for(:controller=>"tag",:action=>"edit_preview")}', {method: 'get', parameters: 'tags=' + $F('start')})" %><%= submit_tag "Save" %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= render :partial => "footer" %>
|
|
||||||
|
|
||||||
<div id="preview">
|
|
||||||
</div>
|
|
||||||
19
app/views/explore/posts/_date_explore.html.erb
Normal file
19
app/views/explore/posts/_date_explore.html.erb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<aside id="sidebar">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<%= link_to "«".html_safe, popular_explore_posts_path(:date => post_set.presenter.prev_day, :scale => "day") %>
|
||||||
|
<%= link_to "»".html_safe, popular_explore_posts_path(:date => post_set.presenter.next_day, :scale => "day") %>
|
||||||
|
<%= link_to "Day", popular_explore_posts_path(:date => post_set.presenter.date, :scale => "day") %>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= link_to "«".html_safe, popular_explore_posts_path(:date => post_set.presenter.prev_week, :scale => "week") %>
|
||||||
|
<%= link_to "»".html_safe, popular_explore_posts_path(:date => post_set.presenter.next_week, :scale => "week") %>
|
||||||
|
<%= link_to "Week", popular_explore_posts_path(:date => post_set.presenter.date, :scale => "week") %>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= link_to "«".html_safe, popular_explore_posts_path(:date => post_set.presenter.prev_month, :scale => "month") %>
|
||||||
|
<%= link_to "»".html_safe, popular_explore_posts_path(:date => post_set.presenter.next_month, :scale => "month") %>
|
||||||
|
<%= link_to "Month", popular_explore_posts_path(:date => post_set.presenter.date, :scale => "month") %>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
14
app/views/explore/posts/popular.html.erb
Normal file
14
app/views/explore/posts/popular.html.erb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<div id="c-explore-posts">
|
||||||
|
<div id="a-index">
|
||||||
|
<h1>Explore: <%= @post_set.min_date %> – <%= @post_set.max_date %></h1>
|
||||||
|
|
||||||
|
<%= render "date_explore", :post_set => @post_set %>
|
||||||
|
|
||||||
|
<section id="content">
|
||||||
|
<%= @post_set.presenter.post_previews_html(self) %>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= render "posts/partials/common/secondary_links" %>
|
||||||
|
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header id="top">
|
<header id="top">
|
||||||
|
<%= render "news/listing" %>
|
||||||
|
|
||||||
<h1><%= link_to Danbooru.config.app_name, "/" %></h1>
|
<h1><%= link_to Danbooru.config.app_name, "/" %></h1>
|
||||||
<nav>
|
<nav>
|
||||||
<menu class="main">
|
<menu class="main">
|
||||||
@@ -64,5 +66,7 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<%= yield :page_footer_content %>
|
<%= yield :page_footer_content %>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<%= render "static/footer" %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
21
app/views/moderator/tags/edit.html.erb
Normal file
21
app/views/moderator/tags/edit.html.erb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<div id="c-moderator-tags">
|
||||||
|
<div id="a-edit">
|
||||||
|
<h1>Edit Tags</h1>
|
||||||
|
|
||||||
|
<%= form_tag(moderator_tag_path, :method => :put) do %>
|
||||||
|
<div class="input">
|
||||||
|
<label>Predicate</label>
|
||||||
|
<%= text_field :tag, :predicate %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input">
|
||||||
|
<label>Consequent</label>
|
||||||
|
<%= text_field :tag, :consequent %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input">
|
||||||
|
<%= submit_tag %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
6
app/views/news/_listing.html.erb
Normal file
6
app/views/news/_listing.html.erb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<div id="news-ticker">
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a href="#" id="close-news-ticker-link">close</a>
|
||||||
|
</div>
|
||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
<%= render :partial => "posts/partials/index/mode_menu" %>
|
<%= render :partial => "posts/partials/index/mode_menu" %>
|
||||||
|
|
||||||
<%= render :partial => "posts/partials/index/blacklist" %>
|
|
||||||
|
|
||||||
<section id="tag-box">
|
<section id="tag-box">
|
||||||
<h1>Tags</h1>
|
<h1>Tags</h1>
|
||||||
<%= @post_set.presenter.tag_list_html(self) %>
|
<%= @post_set.presenter.tag_list_html(self) %>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<%= render :partial => "posts/partials/index/blacklist" %>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<section id="content">
|
<section id="content">
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<menu>
|
<menu>
|
||||||
<li><%= link_to "Listing", posts_path %></li>
|
<li><%= link_to "Listing", posts_path %></li>
|
||||||
<li><%= link_to "Upload", new_upload_path %></li>
|
<li><%= link_to "Upload", new_upload_path %></li>
|
||||||
<li><%= link_to "Popular", explore_post_popular_path %></li>
|
<li><%= link_to "Popular", popular_explore_posts_path %></li>
|
||||||
<li><%= link_to "Hot", explore_post_hot_path %></li>
|
<li><%= link_to "Hot", posts_path(:tags => "order:rank") %></li>
|
||||||
<% unless CurrentUser.is_anonymous? %>
|
<% unless CurrentUser.is_anonymous? %>
|
||||||
<li><%= link_to "Favorites", favorites_path %></li>
|
<li><%= link_to "Favorites", favorites_path %></li>
|
||||||
<li><%= link_to "Subscriptions", posts_tag_subscription_path(CurrentUser.id) %></li>
|
<li><%= link_to "Subscriptions", posts_tag_subscription_path(CurrentUser.id) %></li>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<section id="blacklist-box">
|
<section id="blacklist-box">
|
||||||
<h1>Blacklisted</h1>
|
<h1>Blacklisted</h1>
|
||||||
<%= link_to "Hidden", "#" %>
|
<ul id="blacklist-list">
|
||||||
<ul>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
<li><%= link_to "Flag", new_post_flag_path(:post_id => post.id), :id => "flag" %></li>
|
<li><%= link_to "Flag", new_post_flag_path(:post_id => post.id), :id => "flag" %></li>
|
||||||
<li><%= link_to "Appeal", new_post_appeal_path(:post_id => post.id), :id => "appeal" %></li>
|
<li><%= link_to "Appeal", new_post_appeal_path(:post_id => post.id), :id => "appeal" %></li>
|
||||||
<% if CurrentUser.is_janitor? %>
|
<% if CurrentUser.is_janitor? %>
|
||||||
<li><%= link_to "Approve", moderation_post_approval_path(:post_id => post.id), :remote => true, :method => :post, :id => "approve" %></li>
|
<li><%= link_to "Approve", moderator_post_approval_path(:post_id => post.id), :remote => true, :method => :post, :id => "approve" %></li>
|
||||||
<li><%= link_to "Disapprove", moderation_post_approval_path(:post_id => post.id), :remote => true, :method => :destroy, :id => "disapprove" %></li>
|
<li><%= link_to "Disapprove", moderator_post_disapproval_path(:post_id => post.id), :remote => true, :method => :post, :id => "disapprove" %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if CurrentUser.is_moderator? %>
|
<% if CurrentUser.is_moderator? %>
|
||||||
<li><%= link_to "Undelete", moderation_post_deletion_path(:post_id => post.id), :remote => true, :method => :destroy, :id => "undelete" %></li>
|
<li><%= link_to "Undelete", undelete_moderator_post_post_path(:post_id => post.id), :remote => true, :method => :post, :id => "undelete" %></li>
|
||||||
<li><%= link_to "Delete", moderation_post_deletion_path(:post_id => post.id), :remote => true, :method => :post, :id => "delete" %></li>
|
<li><%= link_to "Delete", delete_moderator_post_post_path(:post_id => post.id), :remote => true, :method => :post, :id => "delete" %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li><%= link_to "Pool", "#", :id => "pool" %></li>
|
<li><%= link_to "Pool", "#", :id => "pool" %></li>
|
||||||
</ul>
|
</ul>
|
||||||
3
app/views/static/_footer.html.erb
Normal file
3
app/views/static/_footer.html.erb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<footer id="page-footer">
|
||||||
|
Running Danbooru v<%= Danbooru.config.version %>. <%= mail_to Danbooru.config.contact_email, "Contact", :encode => :hex %>.
|
||||||
|
</footer>
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<div id="jquery-test">
|
|
||||||
<div class="note" id="lots-of-text-1">
|
|
||||||
Lorem ipsum
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="note" id="lots-of-text-2" style="left: 400px;">
|
|
||||||
Lorem ipsum
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var body = $("#lots-of-text-2");
|
|
||||||
body.css({height: "auto", minWidth: 140});
|
|
||||||
|
|
||||||
var w = body[0].offsetWidth;
|
|
||||||
var h = body[0].offsetHeight;
|
|
||||||
var lo = null;
|
|
||||||
var hi = null;
|
|
||||||
var x = null;
|
|
||||||
var last = null;
|
|
||||||
|
|
||||||
if (body[0].scrollWidth <= body[0].clientWidth) {
|
|
||||||
lo = 20, hi = w
|
|
||||||
|
|
||||||
do {
|
|
||||||
x = (lo+hi)/2
|
|
||||||
body.css({minWidth: x});
|
|
||||||
|
|
||||||
if (body[0].offsetHeight > h) {
|
|
||||||
lo = x;
|
|
||||||
} else {
|
|
||||||
hi = x;
|
|
||||||
}
|
|
||||||
} while ((hi - lo) > 4);
|
|
||||||
|
|
||||||
if (body[0].offsetHeight > h) {
|
|
||||||
body.css({minWidth: hi});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<div style="width: 40em; margin: 5em auto; overflow: scroll;">
|
<div style="width: 40em; margin: 5em auto; overflow: scroll;">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h4>Terms of Service</h4>
|
<h1>Terms of Service</h1>
|
||||||
<p>By accessing the "<%= Danbooru.config.app_name %>" website ("Site") you agree to the following terms of service. If you do not agree to these terms, then please do not access the Site.</p>
|
<p>By accessing the "<%= Danbooru.config.app_name %>" website ("Site") you agree to the following terms of service. If you do not agree to these terms, then please do not access the Site.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h6>Post/Comment Limiting</h6>
|
<h1>Post/Comment Limiting</h1>
|
||||||
<p>You cannot upload a post or comment during the first week of signing up.</p>
|
<p>You cannot upload a post or comment during the first week of signing up.</p>
|
||||||
<p>After the initial period, you can post up to one comment an hour and a variable number of posts based on how many of your previous uploads were approved or deleted.</p>
|
<p>After the initial period, you can post up to one comment an hour and a variable number of posts based on how many of your previous uploads were approved or deleted.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h6>Prohibited Content</h6>
|
<h1>Prohibited Content</h1>
|
||||||
<p>In addition, you may not use the Site to upload any of the following:</p>
|
<p>In addition, you may not use the Site to upload any of the following:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Non-anime: Photographs of American porn actresses, for example, are prohibited. Photographs of cosplayers, figures, or prominent figures in the industry are acceptable.</li>
|
<li>Non-anime: Photographs of American porn actresses, for example, are prohibited. Photographs of cosplayers, figures, or prominent figures in the industry are acceptable.</li>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h4>Copyright Infringement</h4>
|
<h1>Copyright Infringement</h1>
|
||||||
|
|
||||||
<p>If you believe a post infringes upon your copyright, please send an email to the <%= mail_to Danbooru.config.contact_email, "webmaster", :encode => "hex" %> with the following pieces of information:</p>
|
<p>If you believe a post infringes upon your copyright, please send an email to the <%= mail_to Danbooru.config.contact_email, "webmaster", :encode => "hex" %> with the following pieces of information:</p>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -45,14 +45,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h4>Privacy Policy</h4>
|
<h1>Privacy Policy</h1>
|
||||||
|
|
||||||
<p>The Site will not disclose the IP address, email address, password, or DMails of any user except to the staff.</p>
|
<p>The Site will not disclose the IP address, email address, password, or DMails of any user except to the staff.</p>
|
||||||
<p>The Site is allowed to make public everything else, including but not limited to: uploaded posts, favorited posts, comments, forum posts, wiki edits, and note edits.</p>
|
<p>The Site is allowed to make public everything else, including but not limited to: uploaded posts, favorited posts, comments, forum posts, wiki edits, and note edits.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4>Agreement</h4>
|
<h1>Agreement</h1>
|
||||||
<p>By clicking on the "I Agree" link, you have read all the terms and have agreed to them.</p>
|
<p>By clicking on the "I Agree" link, you have read all the terms and have agreed to them.</p>
|
||||||
<p><%= link_to("I Agree", params[:url] || "/", :onclick => "Cookie.put('tos', '1')") %> | <%= link_to("Cancel", "/") %></p>
|
<p><%= link_to("I Agree", params[:url] || "/", :onclick => "Cookie.put('tos', '1')") %> | <%= link_to("Cancel", "/") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ require File.expand_path('../boot', __FILE__)
|
|||||||
|
|
||||||
require 'rails/all'
|
require 'rails/all'
|
||||||
|
|
||||||
# If you have a Gemfile, require the gems listed there, including any gems
|
# If you have a Gemfile, require the default gems, the ones in the
|
||||||
# you've limited to :test, :development, or :production.
|
# current environment and also include :assets gems if in development
|
||||||
Bundler.require(:default, Rails.env) if defined?(Bundler)
|
# or test environments.
|
||||||
|
Bundler.require *Rails.groups(:assets) if defined?(Bundler)
|
||||||
|
|
||||||
module Danbooru
|
module Danbooru
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module Danbooru
|
|||||||
|
|
||||||
# Contact email address of the admin.
|
# Contact email address of the admin.
|
||||||
def contact_email
|
def contact_email
|
||||||
"webmaster#{server_host}"
|
"webmaster@#{server_host}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stripped of any special characters.
|
# Stripped of any special characters.
|
||||||
|
|||||||
@@ -21,4 +21,7 @@ Danbooru::Application.configure do
|
|||||||
|
|
||||||
# Only use best-standards-support built into browsers
|
# Only use best-standards-support built into browsers
|
||||||
config.action_dispatch.best_standards_support = :builtin
|
config.action_dispatch.best_standards_support = :builtin
|
||||||
|
|
||||||
|
# Do not compress assets
|
||||||
|
config.assets.compress = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ Danbooru::Application.configure do
|
|||||||
# Disable Rails's static asset server (Apache or nginx will already do this)
|
# Disable Rails's static asset server (Apache or nginx will already do this)
|
||||||
config.serve_static_assets = false
|
config.serve_static_assets = false
|
||||||
|
|
||||||
# Compress both stylesheets and JavaScripts
|
# Compress JavaScripts and CSS
|
||||||
config.assets.js_compressor = :uglifier
|
config.assets.compress = true
|
||||||
config.assets.css_compressor = :scss
|
|
||||||
|
|
||||||
# Specifies the header that your server uses for sending files
|
# Specifies the header that your server uses for sending files
|
||||||
# (comment out if your front-end server doesn't support this)
|
# (comment out if your front-end server doesn't support this)
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
ActiveSupport::Inflector.inflections do |inflect|
|
# Be sure to restart your server when you modify this file.
|
||||||
# inflect.plural /^(ox)$/i, '\1en'
|
|
||||||
# inflect.singular /^(ox)en/i, '\1'
|
# Add new inflection rules using the following format
|
||||||
# inflect.irregular 'person', 'people'
|
# (all these examples are active by default):
|
||||||
end
|
# ActiveSupport::Inflector.inflections do |inflect|
|
||||||
|
# inflect.plural /^(ox)$/i, '\1en'
|
||||||
|
# inflect.singular /^(ox)en/i, '\1'
|
||||||
|
# inflect.irregular 'person', 'people'
|
||||||
|
# inflect.uncountable %w( fish sheep )
|
||||||
|
# end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
#
|
#
|
||||||
# This file contains the settings for ActionController::ParametersWrapper
|
# This file contains settings for ActionController::ParamsWrapper which
|
||||||
# which will be enabled by default in the upcoming version of Ruby on Rails.
|
# is enabled by default.
|
||||||
|
|
||||||
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||||
ActionController::Base.wrap_parameters format: [:json]
|
ActionController::Base.wrap_parameters format: [:json]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Danbooru::Application.routes.draw do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :invitations, :only => [:new, :create, :index]
|
resources :invitations, :only => [:new, :create, :index]
|
||||||
resource :tag
|
resource :tag, :only => [:edit, :update]
|
||||||
namespace :post do
|
namespace :post do
|
||||||
resource :dashboard, :only => [:show]
|
resource :dashboard, :only => [:show]
|
||||||
resource :approval, :only => [:create]
|
resource :approval, :only => [:create]
|
||||||
@@ -125,9 +125,11 @@ Danbooru::Application.routes.draw do
|
|||||||
resources :wiki_page_versions, :only => [:index, :show]
|
resources :wiki_page_versions, :only => [:index, :show]
|
||||||
|
|
||||||
namespace :explore do
|
namespace :explore do
|
||||||
namespace :post do
|
resources :posts, :only => [:popular, :hot] do
|
||||||
resource :popular, :only => [:show]
|
collection do
|
||||||
resource :hot, :only => [:show]
|
get :popular
|
||||||
|
get :hot
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
5
config/schedule.rb
Normal file
5
config/schedule.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
set :output, "/var/log/whenever.log"
|
||||||
|
|
||||||
|
every 1.hour do
|
||||||
|
TagSubscription.process_all
|
||||||
|
end
|
||||||
@@ -2250,7 +2250,9 @@ CREATE TABLE tag_aliases (
|
|||||||
antecedent_name character varying(255) NOT NULL,
|
antecedent_name character varying(255) NOT NULL,
|
||||||
consequent_name character varying(255) NOT NULL,
|
consequent_name character varying(255) NOT NULL,
|
||||||
creator_id integer NOT NULL,
|
creator_id integer NOT NULL,
|
||||||
|
creator_ip_addr inet NOT NULL,
|
||||||
forum_topic_id integer,
|
forum_topic_id integer,
|
||||||
|
status character varying(255) DEFAULT 'pending'::character varying NOT NULL,
|
||||||
created_at timestamp without time zone,
|
created_at timestamp without time zone,
|
||||||
updated_at timestamp without time zone
|
updated_at timestamp without time zone
|
||||||
);
|
);
|
||||||
@@ -2285,7 +2287,9 @@ CREATE TABLE tag_implications (
|
|||||||
consequent_name character varying(255) NOT NULL,
|
consequent_name character varying(255) NOT NULL,
|
||||||
descendant_names text NOT NULL,
|
descendant_names text NOT NULL,
|
||||||
creator_id integer NOT NULL,
|
creator_id integer NOT NULL,
|
||||||
|
creator_ip_addr inet NOT NULL,
|
||||||
forum_topic_id integer,
|
forum_topic_id integer,
|
||||||
|
status character varying(255) DEFAULT 'pending'::character varying NOT NULL,
|
||||||
created_at timestamp without time zone,
|
created_at timestamp without time zone,
|
||||||
updated_at timestamp without time zone
|
updated_at timestamp without time zone
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ class CreateTagAliases < ActiveRecord::Migration
|
|||||||
t.column :antecedent_name, :string, :null => false
|
t.column :antecedent_name, :string, :null => false
|
||||||
t.column :consequent_name, :string, :null => false
|
t.column :consequent_name, :string, :null => false
|
||||||
t.column :creator_id, :integer, :null => false
|
t.column :creator_id, :integer, :null => false
|
||||||
|
t.column :creator_ip_addr, :inet, :null => false
|
||||||
t.column :forum_topic_id, :integer
|
t.column :forum_topic_id, :integer
|
||||||
|
t.column :status, :text, :null => false, :default => "pending"
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ class CreateTagImplications < ActiveRecord::Migration
|
|||||||
t.column :consequent_name, :string, :null => false
|
t.column :consequent_name, :string, :null => false
|
||||||
t.column :descendant_names, :text, :null => false
|
t.column :descendant_names, :text, :null => false
|
||||||
t.column :creator_id, :integer, :null => false
|
t.column :creator_id, :integer, :null => false
|
||||||
|
t.column :creator_ip_addr, :inet, :null => false
|
||||||
t.column :forum_topic_id, :integer
|
t.column :forum_topic_id, :integer
|
||||||
|
t.column :status, :text, :null => false, :default => "pending"
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,550 +0,0 @@
|
|||||||
.blacklisted {
|
|
||||||
display: none !important; }
|
|
||||||
|
|
||||||
body, div, h1, h2, h3, h4, h5, h6, p, ul, li, dd, dt, header, aside {
|
|
||||||
font-family: Verdana, Geneva, sans-serif;
|
|
||||||
line-height: 1.25em; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-size: 87.5%; }
|
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
|
||||||
font-family: Tahoma;
|
|
||||||
line-height: 1em; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
padding: 1em 2em;
|
|
||||||
margin: 0; }
|
|
||||||
|
|
||||||
article, section {
|
|
||||||
display: block; }
|
|
||||||
|
|
||||||
a:link {
|
|
||||||
color: #006ffa;
|
|
||||||
text-decoration: none; }
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #006ffa;
|
|
||||||
text-decoration: none; }
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #9093ff;
|
|
||||||
text-decoration: none; }
|
|
||||||
|
|
||||||
a:active {
|
|
||||||
color: #006ffa;
|
|
||||||
text-decoration: none; }
|
|
||||||
|
|
||||||
abbr[title=required] {
|
|
||||||
display: none; }
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 0 0 1em 0;
|
|
||||||
padding: 1em;
|
|
||||||
border: 1px solid #666;
|
|
||||||
background: #EEE; }
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 1.2em; }
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: bold; }
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 2.1818em; }
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 1.9091em; }
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.6364em; }
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 1.4545em; }
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.2727em; }
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1.090em; }
|
|
||||||
|
|
||||||
header {
|
|
||||||
margin: 0 0 1em 0;
|
|
||||||
padding: 0;
|
|
||||||
display: block; }
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: none;
|
|
||||||
vertical-align: middle; }
|
|
||||||
|
|
||||||
input[type=text], input[type=password], input[type=url], textarea, button {
|
|
||||||
/* border: 1px solid #AAA;*/
|
|
||||||
font-size: 1em;
|
|
||||||
/* -moz-border-radius: 4px;*/
|
|
||||||
/* -webkit-border-radius: 4px;*/ }
|
|
||||||
|
|
||||||
input[type=submit] {
|
|
||||||
padding: 1px 4px;
|
|
||||||
/* border: 1px solid #AAA;*/
|
|
||||||
/* background-color: #EEE;*/
|
|
||||||
/* -moz-border-radius: 4px;*/
|
|
||||||
/* -webkit-border-radius: 4px;*/
|
|
||||||
font-size: 1em;
|
|
||||||
cursor: pointer; }
|
|
||||||
|
|
||||||
input:focus, textarea:focus {
|
|
||||||
/* background-color: #FFD;*/ }
|
|
||||||
|
|
||||||
input[type=submit]:hover {
|
|
||||||
/* background-color: #F6F6F6;*/ }
|
|
||||||
|
|
||||||
menu {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0; }
|
|
||||||
menu ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0; }
|
|
||||||
menu li {
|
|
||||||
margin: 0 1em 0 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style-type: none;
|
|
||||||
display: inline; }
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
section {
|
|
||||||
display: block; }
|
|
||||||
|
|
||||||
span.error {
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
color: red; }
|
|
||||||
|
|
||||||
span.link {
|
|
||||||
color: #006ffa;
|
|
||||||
cursor: pointer; }
|
|
||||||
|
|
||||||
span.wait {
|
|
||||||
color: #CCC; }
|
|
||||||
|
|
||||||
span.ui-icon {
|
|
||||||
float: left;
|
|
||||||
margin-right: 0.25em; }
|
|
||||||
|
|
||||||
table tfoot {
|
|
||||||
margin-top: 2em; }
|
|
||||||
|
|
||||||
table.striped tbody tr:hover {
|
|
||||||
background-color: #FFE; }
|
|
||||||
table.striped tr.even {
|
|
||||||
background-color: #EEE; }
|
|
||||||
|
|
||||||
div.error-messages {
|
|
||||||
margin: 1em 0;
|
|
||||||
padding: 1em; }
|
|
||||||
div.error-messages span.ui-icon {
|
|
||||||
float: left;
|
|
||||||
margin-right: 0.5em; }
|
|
||||||
div.error-messages h1 {
|
|
||||||
font-size: 1em;
|
|
||||||
color: #A00; }
|
|
||||||
|
|
||||||
div#search {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
div#notice {
|
|
||||||
margin: 1em 0;
|
|
||||||
padding: 1em; }
|
|
||||||
div#notice span.ui-icon {
|
|
||||||
float: left;
|
|
||||||
margin-right: 0.5em; }
|
|
||||||
|
|
||||||
div#page aside#sidebar {
|
|
||||||
width: 20%;
|
|
||||||
float: left; }
|
|
||||||
div#page aside#sidebar h1 {
|
|
||||||
font-size: 1.2em; }
|
|
||||||
div#page aside#sidebar ul {
|
|
||||||
list-style-type: none; }
|
|
||||||
div#page aside#sidebar > section {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
div#page section#content {
|
|
||||||
width: 75%;
|
|
||||||
float: left;
|
|
||||||
margin-left: 2em; }
|
|
||||||
|
|
||||||
div.clearfix {
|
|
||||||
clear: both; }
|
|
||||||
|
|
||||||
/*** Paginator ***/
|
|
||||||
div.paginator {
|
|
||||||
display: block;
|
|
||||||
padding: 2em 0 1em 0;
|
|
||||||
font-size: 1em;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
clear: both; }
|
|
||||||
div.paginator a {
|
|
||||||
margin: 0 3px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
font-weight: normal;
|
|
||||||
border: 1px solid #EAEAEA; }
|
|
||||||
div.paginator a.arrow {
|
|
||||||
border: none; }
|
|
||||||
div.paginator a.arrow:hover {
|
|
||||||
background: white;
|
|
||||||
color: #9093FF; }
|
|
||||||
div.paginator a.current {
|
|
||||||
border: 1px solid #AAA; }
|
|
||||||
div.paginator a:hover {
|
|
||||||
background: #3c3cdc;
|
|
||||||
color: white; }
|
|
||||||
div.paginator span {
|
|
||||||
margin: 0 3px;
|
|
||||||
padding: 2px 6px; }
|
|
||||||
|
|
||||||
/*** Header ***/
|
|
||||||
body > header > h1 {
|
|
||||||
font-size: 3em;
|
|
||||||
font-family: Tahoma, Helvetica, sans-serif; }
|
|
||||||
|
|
||||||
/*** Dialog Boxes ***/
|
|
||||||
div.ui-dialog ul {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
/*** Simple Form ***/
|
|
||||||
form.simple_form {
|
|
||||||
margin: 0 0 1em 0; }
|
|
||||||
form.simple_form div.input.boolean label {
|
|
||||||
display: inline; }
|
|
||||||
form.simple_form div.input {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
form.simple_form div.input input[type=text], form.simple_form div.input input[type=file] {
|
|
||||||
width: 20em; }
|
|
||||||
form.simple_form div.input textarea {
|
|
||||||
width: 30em; }
|
|
||||||
form.simple_form div.input label {
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold; }
|
|
||||||
form.simple_form div.input span.hint {
|
|
||||||
color: #666;
|
|
||||||
font-style: italic;
|
|
||||||
display: block; }
|
|
||||||
form.simple_form div.input fieldset {
|
|
||||||
border: none;
|
|
||||||
display: inline;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0; }
|
|
||||||
form.simple_form div.input fieldset label {
|
|
||||||
font-weight: normal;
|
|
||||||
width: auto;
|
|
||||||
margin-right: 2em; }
|
|
||||||
|
|
||||||
/*** DText Preview ***/
|
|
||||||
div.dtext {
|
|
||||||
width: 30em; }
|
|
||||||
div.dtext ul {
|
|
||||||
margin-left: 1em; }
|
|
||||||
|
|
||||||
/*** Pools Posts ***/
|
|
||||||
div#c-pools-posts div#a-new form {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
div#c-pools-posts div#a-new li {
|
|
||||||
margin-left: 1em;
|
|
||||||
cursor: pointer; }
|
|
||||||
|
|
||||||
/*** Pools ***/
|
|
||||||
div#c-pools div#a-edit p {
|
|
||||||
width: 30em; }
|
|
||||||
div#c-pools div#a-edit ul.ui-sortable {
|
|
||||||
list-style-type: none; }
|
|
||||||
div#c-pools div#a-edit ul.ui-sortable span {
|
|
||||||
margin: 0;
|
|
||||||
float: right;
|
|
||||||
cursor: pointer; }
|
|
||||||
div#c-pools div#a-edit ul.ui-sortable li {
|
|
||||||
padding: 0.5em; }
|
|
||||||
div#c-pools div#a-edit ul.ui-sortable li.ui-state-default {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
width: 180px;
|
|
||||||
background: none; }
|
|
||||||
div#c-pools div#a-edit ul.ui-sortable li.ui-state-placeholder {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
width: 180px;
|
|
||||||
height: 150px;
|
|
||||||
background: none; }
|
|
||||||
|
|
||||||
/*** Comments ***/
|
|
||||||
div.comments-for-post div.list-of-comments article {
|
|
||||||
margin-bottom: 2em; }
|
|
||||||
div.comments-for-post div.list-of-comments article div.author {
|
|
||||||
width: 20%;
|
|
||||||
float: left; }
|
|
||||||
div.comments-for-post div.list-of-comments article div.content {
|
|
||||||
margin-left: 2em;
|
|
||||||
width: 30em;
|
|
||||||
float: left; }
|
|
||||||
div.comments-for-post div.comment-preview {
|
|
||||||
margin-bottom: 2em; }
|
|
||||||
|
|
||||||
div.dtext-preview {
|
|
||||||
border: 2px dashed #AAA;
|
|
||||||
padding: 1em;
|
|
||||||
margin: 1em;
|
|
||||||
width: 30em; }
|
|
||||||
|
|
||||||
div#c-comments div#a-index div.header span.info {
|
|
||||||
margin-right: 1.5em; }
|
|
||||||
div#c-comments div#a-index div.header strong, div#c-comments div#a-index div.header time {
|
|
||||||
margin-right: 0.3em; }
|
|
||||||
div#c-comments div#a-index div.header time {
|
|
||||||
font-weight: bold; }
|
|
||||||
div#c-comments div#a-index div.header div.list-of-tags a {
|
|
||||||
margin-right: 0.5em; }
|
|
||||||
div#c-comments div#a-index div.header div.notices {
|
|
||||||
margin: 1em 0; }
|
|
||||||
div#c-comments div#a-index div.preview {
|
|
||||||
float: left;
|
|
||||||
width: 180px; }
|
|
||||||
div#c-comments div#a-index div.post {
|
|
||||||
margin-bottom: 4em; }
|
|
||||||
div#c-comments div#a-index div.post div.comments-for-post {
|
|
||||||
float: left;
|
|
||||||
width: 55em; }
|
|
||||||
|
|
||||||
/*** Favorites ***/
|
|
||||||
div#c-favorites section#content > h1 {
|
|
||||||
display: none; }
|
|
||||||
|
|
||||||
/*** Posts ***/
|
|
||||||
article.post-preview {
|
|
||||||
margin-right: 4em;
|
|
||||||
margin-bottom: 4em;
|
|
||||||
float: left; }
|
|
||||||
|
|
||||||
div#c-posts div.notice {
|
|
||||||
font-size: 80%;
|
|
||||||
padding: 1em;
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
div#c-posts div.notice ul {
|
|
||||||
margin-left: 1em; }
|
|
||||||
div#c-posts aside#sidebar > section#pool-sidebar span.ui-icon {
|
|
||||||
color: #666; }
|
|
||||||
div#c-posts aside#sidebar > section > ul li {
|
|
||||||
list-style-type: none; }
|
|
||||||
div#c-posts aside#sidebar > section > ul ul li {
|
|
||||||
margin-left: 1em; }
|
|
||||||
div#c-posts section#tag-and-wiki-box {
|
|
||||||
padding: 0; }
|
|
||||||
div#c-posts section#tag-and-wiki-box menu li {
|
|
||||||
display: inline-block; }
|
|
||||||
div#c-posts section#tag-and-wiki-box menu li.active a {
|
|
||||||
color: #000; }
|
|
||||||
div#c-posts section#tag-and-wiki-box div#tag-box h2 {
|
|
||||||
display: none; }
|
|
||||||
div#c-posts section#tag-and-wiki-box div#tag-box li {
|
|
||||||
list-style-type: none; }
|
|
||||||
div#c-posts section#tag-and-wiki-box div#wiki-box h2 {
|
|
||||||
display: none; }
|
|
||||||
div#c-posts section#content > h1 {
|
|
||||||
display: none; }
|
|
||||||
div#c-posts section#content section > h2 {
|
|
||||||
display: none; }
|
|
||||||
div#c-posts section#content menu#post-sections {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
div#c-posts section#content menu#post-sections li {
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold; }
|
|
||||||
div#c-posts section#content menu#post-sections li.active a {
|
|
||||||
color: black; }
|
|
||||||
div#c-posts section#content section#edit fieldset label {
|
|
||||||
display: inline; }
|
|
||||||
|
|
||||||
/*** Post Histories ***/
|
|
||||||
div.post_histories div.index div.post {
|
|
||||||
margin-bottom: 2em; }
|
|
||||||
div.post_histories div.index div.post div.preview {
|
|
||||||
width: 20%;
|
|
||||||
float: left; }
|
|
||||||
div.post_histories div.index div.post div.history {
|
|
||||||
width: 70%;
|
|
||||||
float: left; }
|
|
||||||
div.post_histories div.index div.post div.history table {
|
|
||||||
width: 100%; }
|
|
||||||
div.post_histories div.index div.post div.history ins {
|
|
||||||
color: green;
|
|
||||||
text-decoration: none; }
|
|
||||||
div.post_histories div.index div.post div.history del {
|
|
||||||
color: red;
|
|
||||||
text-decoration: line-through; }
|
|
||||||
|
|
||||||
/*** Post Unapprovals ***/
|
|
||||||
div#unapprove-dialog p {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
/*** Sessions ***/
|
|
||||||
div#sessions div#new section {
|
|
||||||
width: 30em;
|
|
||||||
float: left; }
|
|
||||||
div#sessions div#new aside {
|
|
||||||
width: 20em;
|
|
||||||
float: left; }
|
|
||||||
div#sessions div#new aside li {
|
|
||||||
display: list-item;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
list-style-type: square;
|
|
||||||
margin-left: 1em; }
|
|
||||||
div#sessions div#new h2 {
|
|
||||||
margin-bottom: 5px; }
|
|
||||||
|
|
||||||
/*** Artists ***/
|
|
||||||
div#c-artists span.new-artist {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #A00; }
|
|
||||||
div#c-artists div#a-show {
|
|
||||||
max-width: 60em; }
|
|
||||||
div#c-artists div#a-show p.legend {
|
|
||||||
margin-bottom: 2em;
|
|
||||||
font-size: 0.8em;
|
|
||||||
font-style: italic; }
|
|
||||||
div#c-artists div#a-edit textarea, div#c-artists div#a-new textarea {
|
|
||||||
height: 5em; }
|
|
||||||
|
|
||||||
/*** Users ***/
|
|
||||||
div.users div.new {
|
|
||||||
max-width: 60em; }
|
|
||||||
div.users div.new p {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
div.users div.new li {
|
|
||||||
margin-left: 1em; }
|
|
||||||
div.users div.new div#account-comparison li {
|
|
||||||
font-size: 0.9em;
|
|
||||||
line-height: 1.5em; }
|
|
||||||
div.users div.new div#account-comparison section {
|
|
||||||
width: 18em;
|
|
||||||
float: left;
|
|
||||||
padding: 1em; }
|
|
||||||
div.users div.new footer.nav-links {
|
|
||||||
font-size: 1.4545em;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
display: block; }
|
|
||||||
div.users div.new div#p2 ul {
|
|
||||||
margin-bottom: 2em; }
|
|
||||||
|
|
||||||
/*** Uploads ***/
|
|
||||||
div#c-uploads div#a-new div#upload-guide-notice {
|
|
||||||
margin-bottom: 2em; }
|
|
||||||
div#c-uploads div#a-new fieldset.ratings label {
|
|
||||||
display: inline; }
|
|
||||||
|
|
||||||
/*** Forum ***/
|
|
||||||
div.list-of-forum-posts article {
|
|
||||||
margin-bottom: 3em; }
|
|
||||||
div.list-of-forum-posts article div.author {
|
|
||||||
width: 20%;
|
|
||||||
float: left; }
|
|
||||||
div.list-of-forum-posts article div.content {
|
|
||||||
margin-left: 2em;
|
|
||||||
width: 30em;
|
|
||||||
float: left; }
|
|
||||||
div.list-of-forum-posts article div.content menu {
|
|
||||||
margin-top: 0.5em; }
|
|
||||||
|
|
||||||
div#c-forum-topics div.single-forum-post {
|
|
||||||
width: 60em; }
|
|
||||||
div#c-forum-topics div#a-show h1#forum-topic-title {
|
|
||||||
font-size: 2.1818em; }
|
|
||||||
div#c-forum-topics span.info {
|
|
||||||
color: #AAA; }
|
|
||||||
div#c-forum-topics div#form-content {
|
|
||||||
float: left;
|
|
||||||
width: 450px;
|
|
||||||
padding-right: 1em; }
|
|
||||||
div#c-forum-topics div#form-aside {
|
|
||||||
float: left;
|
|
||||||
width: 400px; }
|
|
||||||
div#c-forum-topics div#form-aside div#preview > p {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
padding-top: 0.5em;
|
|
||||||
border-top: 1px solid #AAA; }
|
|
||||||
|
|
||||||
/*** Wiki Pages ***/
|
|
||||||
div#c-wiki-pages span.version {
|
|
||||||
color: #AAA; }
|
|
||||||
div#c-wiki-pages div#form-content {
|
|
||||||
float: left;
|
|
||||||
width: 30em;
|
|
||||||
padding-right: 1em; }
|
|
||||||
div#c-wiki-pages div#form-aside {
|
|
||||||
float: left;
|
|
||||||
width: 20em; }
|
|
||||||
div#c-wiki-pages div#form-aside div#preview > p {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
padding-top: 0.5em;
|
|
||||||
border-top: 1px solid #AAA; }
|
|
||||||
|
|
||||||
/*** Post Moderation ***/
|
|
||||||
div#c-post-moderation article {
|
|
||||||
margin-bottom: 4em; }
|
|
||||||
div#c-post-moderation aside {
|
|
||||||
float: left;
|
|
||||||
width: 520px; }
|
|
||||||
div#c-post-moderation section {
|
|
||||||
float: left;
|
|
||||||
width: 300px; }
|
|
||||||
|
|
||||||
/*** Note Container ***/
|
|
||||||
div#note-container {
|
|
||||||
position: absolute; }
|
|
||||||
div#note-container div.note-body {
|
|
||||||
background: #FFE;
|
|
||||||
border: 1px solid black;
|
|
||||||
max-width: 300px;
|
|
||||||
min-width: 140px;
|
|
||||||
min-height: 10px;
|
|
||||||
position: absolute;
|
|
||||||
padding: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
overflow: auto; }
|
|
||||||
div#note-container div.note-body p.tn {
|
|
||||||
font-size: 0.8em;
|
|
||||||
color: gray; }
|
|
||||||
div#note-container div.note-box {
|
|
||||||
position: absolute;
|
|
||||||
border: 1px solid black;
|
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
|
||||||
cursor: move;
|
|
||||||
background: #FFE; }
|
|
||||||
div#note-container div.note-box div.note-corner {
|
|
||||||
background: black;
|
|
||||||
width: 7px;
|
|
||||||
height: 7px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
cursor: se-resize; }
|
|
||||||
div#note-container div.unsaved {
|
|
||||||
background: #FFF;
|
|
||||||
border: 1px solid red; }
|
|
||||||
div#note-container div.unsaved div.note-corner {
|
|
||||||
background: red; }
|
|
||||||
|
|
||||||
div#jquery-test div.note {
|
|
||||||
background: #FFE;
|
|
||||||
border: 1px solid black;
|
|
||||||
max-width: 300px;
|
|
||||||
min-width: 140px;
|
|
||||||
min-height: 10px;
|
|
||||||
position: absolute;
|
|
||||||
padding: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
overflow: auto; }
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
psql -c "UPDATE posts SET is_flagged = false, is_pending = true, approver_id = null WHERE id = 1" danbooru2
|
|
||||||
psql -c "DELETE FROM unapprovals" danbooru2
|
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
Factory.define(:tag_alias) do |f|
|
FactoryGirl.define do
|
||||||
f.antecedent_name "aaa"
|
factory :tag_alias do
|
||||||
f.consequent_name "bbb"
|
antecedent_name "aaa"
|
||||||
|
consequent_name "bbb"
|
||||||
|
|
||||||
|
after_create do |tag_alias|
|
||||||
|
tag_alias.process!
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
Factory.define(:tag_implication) do |f|
|
FactoryGirl.define do
|
||||||
f.antecedent_name "aaa"
|
factory :tag_implication do
|
||||||
f.consequent_name "bbb"
|
antecedent_name "aaa"
|
||||||
|
consequent_name "bbb"
|
||||||
|
|
||||||
|
after_create do |tag_implication|
|
||||||
|
tag_implication.process!
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
29
test/functional/moderator/tags_controller_test.rb
Normal file
29
test/functional/moderator/tags_controller_test.rb
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
module Moderator
|
||||||
|
class TagsControllerTest < ActionController::TestCase
|
||||||
|
context "The tags controller" do
|
||||||
|
setup do
|
||||||
|
@user = Factory.create(:moderator_user)
|
||||||
|
CurrentUser.user = @user
|
||||||
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
|
@post = Factory.create(:post)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "render the edit action" do
|
||||||
|
get :edit, {}, {:user_id => @user.id}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
should "execute the update action" do
|
||||||
|
post :update, {:tag => {:predicate => "aaa", :consequent => "bbb"}}, {:user_id => @user.id}
|
||||||
|
assert_redirected_to edit_moderator_tag_path
|
||||||
|
end
|
||||||
|
|
||||||
|
should "fail gracefully if the update action fails" do
|
||||||
|
post :update, {:tag => {:predicate => "", :consequent => "bbb"}}, {:user_id => @user.id}
|
||||||
|
assert_redirected_to edit_moderator_tag_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -7,6 +7,7 @@ class TagAliasesControllerTest < ActionController::TestCase
|
|||||||
CurrentUser.user = @user
|
CurrentUser.user = @user
|
||||||
CurrentUser.ip_addr = "127.0.0.1"
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
MEMCACHE.flush_all
|
MEMCACHE.flush_all
|
||||||
|
Delayed::Worker.delay_jobs = false
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class TagImplicationsControllerTest < ActionController::TestCase
|
|||||||
CurrentUser.user = @user
|
CurrentUser.user = @user
|
||||||
CurrentUser.ip_addr = "127.0.0.1"
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
MEMCACHE.flush_all
|
MEMCACHE.flush_all
|
||||||
|
Delayed::Worker.delay_jobs = false
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
|||||||
33
test/unit/moderator/tag_batch_change_test.rb
Normal file
33
test/unit/moderator/tag_batch_change_test.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
module Moderator
|
||||||
|
class TagBatchChangeTest < ActiveSupport::TestCase
|
||||||
|
context "a tag batch change" do
|
||||||
|
setup do
|
||||||
|
@user = Factory.create(:moderator_user)
|
||||||
|
CurrentUser.user = @user
|
||||||
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
|
@post = Factory.create(:post, :tag_string => "aaa")
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
CurrentUser.user = nil
|
||||||
|
CurrentUser.ip_addr = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
should "execute" do
|
||||||
|
tag_batch_change = TagBatchChange.new("aaa", "bbb")
|
||||||
|
tag_batch_change.execute
|
||||||
|
@post.reload
|
||||||
|
assert_equal("bbb", @post.tag_string)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "raise an error if there is no predicate" do
|
||||||
|
tag_batch_change = TagBatchChange.new("", "bbb")
|
||||||
|
assert_raises(TagBatchChange::Error) do
|
||||||
|
tag_batch_change.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -525,7 +525,13 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
assert_equal(post2.id, relation.first.id)
|
assert_equal(post2.id, relation.first.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "return posts for a tag subscription search"
|
should "return posts for a tag subscription search" do
|
||||||
|
post1 = Factory.create(:post, :tag_string => "aaa")
|
||||||
|
sub = Factory.create(:tag_subscription, :tag_query => "aaa", :name => "zzz")
|
||||||
|
TagSubscription.process_all
|
||||||
|
relation = Post.tag_match("sub:#{CurrentUser.name}")
|
||||||
|
assert_equal(1, relation.count)
|
||||||
|
end
|
||||||
|
|
||||||
should "return posts for a particular rating" do
|
should "return posts for a particular rating" do
|
||||||
post1 = Factory.create(:post, :rating => "s")
|
post1 = Factory.create(:post, :rating => "s")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
require_relative '../test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class TagAliasTest < ActiveSupport::TestCase
|
class TagAliasTest < ActiveSupport::TestCase
|
||||||
context "A tag alias" do
|
context "A tag alias" do
|
||||||
@@ -15,14 +15,14 @@ class TagAliasTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "populate the creator information" do
|
should "populate the creator information" do
|
||||||
ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ta = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
assert_equal(CurrentUser.user.id, ta.creator_id)
|
assert_equal(CurrentUser.user.id, ta.creator_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "convert a tag to its normalized version" do
|
should "convert a tag to its normalized version" do
|
||||||
tag1 = Factory.create(:tag, :name => "aaa")
|
tag1 = Factory.create(:tag, :name => "aaa")
|
||||||
tag2 = Factory.create(:tag, :name => "bbb")
|
tag2 = Factory.create(:tag, :name => "bbb")
|
||||||
ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ta = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
normalized_tags = TagAlias.to_aliased(["aaa", "ccc"])
|
normalized_tags = TagAlias.to_aliased(["aaa", "ccc"])
|
||||||
assert_equal(["bbb", "ccc"], normalized_tags.sort)
|
assert_equal(["bbb", "ccc"], normalized_tags.sort)
|
||||||
end
|
end
|
||||||
@@ -30,7 +30,7 @@ class TagAliasTest < ActiveSupport::TestCase
|
|||||||
should "update the cache" do
|
should "update the cache" do
|
||||||
tag1 = Factory.create(:tag, :name => "aaa")
|
tag1 = Factory.create(:tag, :name => "aaa")
|
||||||
tag2 = Factory.create(:tag, :name => "bbb")
|
tag2 = Factory.create(:tag, :name => "bbb")
|
||||||
ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ta = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
assert_equal("bbb", MEMCACHE.get("ta:aaa"))
|
assert_equal("bbb", MEMCACHE.get("ta:aaa"))
|
||||||
ta.destroy
|
ta.destroy
|
||||||
assert_nil(MEMCACHE.get("ta:aaa"))
|
assert_nil(MEMCACHE.get("ta:aaa"))
|
||||||
@@ -42,7 +42,7 @@ class TagAliasTest < ActiveSupport::TestCase
|
|||||||
post2 = Factory.create(:post, :tag_string => "ccc ddd")
|
post2 = Factory.create(:post, :tag_string => "ccc ddd")
|
||||||
assert_equal("aaa bbb", post1.tag_string)
|
assert_equal("aaa bbb", post1.tag_string)
|
||||||
assert_equal("ccc ddd", post2.tag_string)
|
assert_equal("ccc ddd", post2.tag_string)
|
||||||
ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "ccc")
|
ta = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "ccc")
|
||||||
post1.reload
|
post1.reload
|
||||||
post2.reload
|
post2.reload
|
||||||
assert_equal("ccc bbb", post1.tag_string)
|
assert_equal("ccc bbb", post1.tag_string)
|
||||||
@@ -50,7 +50,7 @@ class TagAliasTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "not validate for transitive relations" do
|
should "not validate for transitive relations" do
|
||||||
ta1 = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ta1 = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
assert_difference("TagAlias.count", 0) do
|
assert_difference("TagAlias.count", 0) do
|
||||||
ta3 = Factory.build(:tag_alias, :antecedent_name => "bbb", :consequent_name => "ddd")
|
ta3 = Factory.build(:tag_alias, :antecedent_name => "bbb", :consequent_name => "ddd")
|
||||||
ta3.save
|
ta3.save
|
||||||
@@ -60,15 +60,15 @@ class TagAliasTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "record the alias's creator in the tag history" do
|
should "record the alias's creator in the tag history" do
|
||||||
user = Factory.create(:user)
|
uploader = Factory.create(:user)
|
||||||
p1 = nil
|
post = nil
|
||||||
CurrentUser.scoped(user, "127.0.0.1") do
|
CurrentUser.scoped(uploader, "127.0.0.1") do
|
||||||
p1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
post = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
end
|
end
|
||||||
ta1 = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "xxx")
|
tag_alias = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "xxx")
|
||||||
p1.reload
|
post.reload
|
||||||
assert_not_equal(ta1.creator_id, p1.uploader_id)
|
assert_not_equal(tag_alias.creator_id, post.uploader_id)
|
||||||
assert_equal(ta1.creator_id, p1.versions.last.updater_id)
|
assert_equal(tag_alias.creator_id, post.versions.last.updater_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "populate the creator information" do
|
should "populate the creator information" do
|
||||||
ti = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
assert_equal(CurrentUser.user.id, ti.creator_id)
|
assert_equal(CurrentUser.user.id, ti.creator_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "not validate when a circular relation is created" do
|
should "not validate when a circular relation is created" do
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
ti2 = Factory.build(:tag_implication, :antecedent_name => "bbb", :consequent_name => "aaa")
|
ti2 = Factory.build(:tag_implication, :antecedent_name => "bbb", :consequent_name => "aaa")
|
||||||
ti2.save
|
ti2.save
|
||||||
assert(ti2.errors.any?, "Tag implication should not have validated.")
|
assert(ti2.errors.any?, "Tag implication should not have validated.")
|
||||||
@@ -29,34 +29,18 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "not allow for duplicates" do
|
should "not allow for duplicates" do
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
ti2 = Factory.build(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti2 = Factory.build(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
ti2.save
|
ti2.save
|
||||||
assert(ti2.errors.any?, "Tag implication should not have validated.")
|
assert(ti2.errors.any?, "Tag implication should not have validated.")
|
||||||
assert_equal("Antecedent name has already been taken", ti2.errors.full_messages.join(""))
|
assert_equal("Antecedent name has already been taken", ti2.errors.full_messages.join(""))
|
||||||
end
|
end
|
||||||
|
|
||||||
should "clear the cache upon saving" do
|
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
|
||||||
assert_equal(["bbb"], ti1.descendant_names_array)
|
|
||||||
assert_equal(["bbb"], MEMCACHE.get("ti:aaa"))
|
|
||||||
ti1.update_attributes(
|
|
||||||
:consequent_name => "ccc"
|
|
||||||
)
|
|
||||||
assert_equal(["ccc"], MEMCACHE.get("ti:aaa"))
|
|
||||||
end
|
|
||||||
|
|
||||||
should "clear the cache upon destruction" do
|
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
|
||||||
ti1.destroy
|
|
||||||
assert_nil(MEMCACHE.get("ti:aaa"))
|
|
||||||
end
|
|
||||||
|
|
||||||
should "calculate all its descendants" do
|
should "calculate all its descendants" do
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "bbb", :consequent_name => "ccc")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "bbb", :consequent_name => "ccc")
|
||||||
assert_equal("ccc", ti1.descendant_names)
|
assert_equal("ccc", ti1.descendant_names)
|
||||||
assert_equal(["ccc"], ti1.descendant_names_array)
|
assert_equal(["ccc"], ti1.descendant_names_array)
|
||||||
ti2 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti2 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
assert_equal("bbb ccc", ti2.descendant_names)
|
assert_equal("bbb ccc", ti2.descendant_names)
|
||||||
assert_equal(["bbb", "ccc"], ti2.descendant_names_array)
|
assert_equal(["bbb", "ccc"], ti2.descendant_names_array)
|
||||||
ti1.reload
|
ti1.reload
|
||||||
@@ -64,15 +48,9 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
assert_equal(["ccc"], ti1.descendant_names_array)
|
assert_equal(["ccc"], ti1.descendant_names_array)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "cache its descendants" do
|
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
|
||||||
assert_equal(["bbb"], ti1.descendant_names_array)
|
|
||||||
assert_equal(["bbb"], MEMCACHE.get("ti:aaa"))
|
|
||||||
end
|
|
||||||
|
|
||||||
should "update its descendants on save" do
|
should "update its descendants on save" do
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
ti2 = Factory.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "ddd")
|
ti2 = FactoryGirl.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "ddd")
|
||||||
ti2.update_attributes(
|
ti2.update_attributes(
|
||||||
:antecedent_name => "bbb"
|
:antecedent_name => "bbb"
|
||||||
)
|
)
|
||||||
@@ -83,10 +61,10 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "update the decendants for its parent on save" do
|
should "update the decendants for its parent on save" do
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
|
||||||
ti2 = Factory.create(:tag_implication, :antecedent_name => "bbb", :consequent_name => "ccc")
|
ti2 = FactoryGirl.create(:tag_implication, :antecedent_name => "bbb", :consequent_name => "ccc")
|
||||||
ti3 = Factory.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "ddd")
|
ti3 = FactoryGirl.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "ddd")
|
||||||
ti4 = Factory.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "eee")
|
ti4 = FactoryGirl.create(:tag_implication, :antecedent_name => "ccc", :consequent_name => "eee")
|
||||||
ti1.reload
|
ti1.reload
|
||||||
ti2.reload
|
ti2.reload
|
||||||
ti3.reload
|
ti3.reload
|
||||||
@@ -99,8 +77,8 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
should "update any affected post upon save" do
|
should "update any affected post upon save" do
|
||||||
p1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
p1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx")
|
||||||
ti2 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "yyy")
|
ti2 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "yyy")
|
||||||
p1.reload
|
p1.reload
|
||||||
assert_equal("aaa yyy xxx bbb ccc", p1.tag_string)
|
assert_equal("aaa yyy xxx bbb ccc", p1.tag_string)
|
||||||
end
|
end
|
||||||
@@ -111,7 +89,7 @@ class TagImplicationTest < ActiveSupport::TestCase
|
|||||||
CurrentUser.scoped(user, "127.0.0.1") do
|
CurrentUser.scoped(user, "127.0.0.1") do
|
||||||
p1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
p1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
end
|
end
|
||||||
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx")
|
ti1 = FactoryGirl.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx")
|
||||||
p1.reload
|
p1.reload
|
||||||
assert_not_equal(ti1.creator_id, p1.uploader_id)
|
assert_not_equal(ti1.creator_id, p1.uploader_id)
|
||||||
assert_equal(ti1.creator_id, p1.versions.last.updater_id)
|
assert_equal(ti1.creator_id, p1.versions.last.updater_id)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class TagTest < ActiveSupport::TestCase
|
|||||||
CurrentUser.user = user
|
CurrentUser.user = user
|
||||||
CurrentUser.ip_addr = "127.0.0.1"
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
MEMCACHE.flush_all
|
MEMCACHE.flush_all
|
||||||
|
Delayed::Worker.delay_jobs = false
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
|
|||||||
BIN
tmp/test.jpg
Normal file
BIN
tmp/test.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Reference in New Issue
Block a user