more work
This commit is contained in:
parent
95b4906e6e
commit
578c96d653
|
@ -211,6 +211,9 @@ $(document).ready(function() {
|
||||||
first();
|
first();
|
||||||
|
|
||||||
box.html($("#comment_form").clone());
|
box.html($("#comment_form").clone());
|
||||||
|
box.find("ol").remove();
|
||||||
|
|
||||||
|
box.find("textarea").focus();
|
||||||
|
|
||||||
var el = $("<input type=\"hidden\" " +
|
var el = $("<input type=\"hidden\" " +
|
||||||
"name=\"parent_comment_short_id\" value=\"" +
|
"name=\"parent_comment_short_id\" value=\"" +
|
||||||
|
|
|
@ -291,7 +291,6 @@ ol.comments {
|
||||||
}
|
}
|
||||||
ol.comments1 {
|
ol.comments1 {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-top: 2em;
|
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
ol.comments.comments1 {
|
ol.comments.comments1 {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class CommentsController < ApplicationController
|
class CommentsController < ApplicationController
|
||||||
before_filter :require_logged_in_user_or_400,
|
before_filter :require_logged_in_user_or_400,
|
||||||
:only => [ :create, :preview, :upvote, :downvote, :unvote ]
|
:only => [ :create, :preview, :upvote, :downvote, :unvote ]
|
||||||
|
before_filter :require_logged_in_user, :only => [ :threads ]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if !(story = Story.find_by_short_id(params[:story_id]))
|
if !(story = Story.find_by_short_id(params[:story_id]))
|
||||||
|
@ -17,24 +18,33 @@ class CommentsController < ApplicationController
|
||||||
params[:parent_comment_short_id])
|
params[:parent_comment_short_id])
|
||||||
comment.parent_comment_id = pc.id
|
comment.parent_comment_id = pc.id
|
||||||
comment.parent_comment_short_id = pc.short_id
|
comment.parent_comment_short_id = pc.short_id
|
||||||
|
comment.thread_id = pc.thread_id
|
||||||
else
|
else
|
||||||
return render :json => { :error => "invalid parent comment",
|
return render :json => { :error => "invalid parent comment",
|
||||||
:status => 400 }
|
:status => 400 }
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
comment.thread_id = Keystore.incremented_value_for("thread_id")
|
||||||
end
|
end
|
||||||
|
|
||||||
if comment.valid? && !params[:preview].present? && comment.save
|
if comment.valid? && !params[:preview].present? && comment.save
|
||||||
comment.current_vote = { :vote => 1 }
|
comment.current_vote = { :vote => 1 }
|
||||||
|
|
||||||
render :partial => "stories/commentbox", :layout => false,
|
if comment.parent_comment_id
|
||||||
:content_type => "text/html", :locals => { :story => story,
|
render :partial => "postedreply", :layout => false,
|
||||||
:comment => Comment.new, :show_comment => comment }
|
:content_type => "text/html", :locals => { :story => story,
|
||||||
|
:show_comment => comment }
|
||||||
|
else
|
||||||
|
render :partial => "commentbox", :layout => false,
|
||||||
|
:content_type => "text/html", :locals => { :story => story,
|
||||||
|
:comment => Comment.new, :show_comment => comment }
|
||||||
|
end
|
||||||
else
|
else
|
||||||
comment.previewing = true
|
comment.previewing = true
|
||||||
comment.upvotes = 1
|
comment.upvotes = 1
|
||||||
comment.current_vote = { :vote => 1 }
|
comment.current_vote = { :vote => 1 }
|
||||||
|
|
||||||
render :partial => "stories/commentbox", :layout => false,
|
render :partial => "commentbox", :layout => false,
|
||||||
:content_type => "text/html", :locals => { :story => story,
|
:content_type => "text/html", :locals => { :story => story,
|
||||||
:comment => comment, :show_comment => comment }
|
:comment => comment, :show_comment => comment }
|
||||||
end
|
end
|
||||||
|
@ -81,4 +91,26 @@ class CommentsController < ApplicationController
|
||||||
|
|
||||||
render :text => "ok"
|
render :text => "ok"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def threads
|
||||||
|
recent_threads = @user.recent_threads
|
||||||
|
|
||||||
|
@threads = recent_threads.map{|r|
|
||||||
|
Comment.ordered_for_story_or_thread_for_user(nil, r, @user.id) }
|
||||||
|
|
||||||
|
# trim each thread to this user's first response
|
||||||
|
@threads.map!{|th|
|
||||||
|
th.each do |c|
|
||||||
|
if c.user_id == @user.id
|
||||||
|
break
|
||||||
|
else
|
||||||
|
th.shift
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
th
|
||||||
|
}
|
||||||
|
|
||||||
|
@comments = @threads.flatten
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ class HomeController < ApplicationController
|
||||||
def index
|
def index
|
||||||
conds = [ "is_expired = 0 " ]
|
conds = [ "is_expired = 0 " ]
|
||||||
|
|
||||||
if @user
|
if @user && !@newest
|
||||||
# exclude downvoted items
|
# exclude downvoted items
|
||||||
conds[0] << "AND stories.id NOT IN (SELECT story_id FROM votes " <<
|
conds[0] << "AND stories.id NOT IN (SELECT story_id FROM votes " <<
|
||||||
"WHERE user_id = ? AND vote < 0) "
|
"WHERE user_id = ? AND vote < 0) "
|
||||||
|
@ -35,11 +35,21 @@ class HomeController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@stories.sort_by!{|s| s.hotness }
|
if @newest
|
||||||
|
# TODO: better algorithm here
|
||||||
|
@stories.sort_by!{|s| s.created_at }.reverse!
|
||||||
|
else
|
||||||
|
@stories.sort_by!{|s| s.hotness }
|
||||||
|
end
|
||||||
|
|
||||||
render :action => "index"
|
render :action => "index"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def newest
|
||||||
|
@newest = true
|
||||||
|
index
|
||||||
|
end
|
||||||
|
|
||||||
def tagged
|
def tagged
|
||||||
if !(@tag = Tag.find_by_tag(params[:tag]))
|
if !(@tag = Tag.find_by_tag(params[:tag]))
|
||||||
raise ActionController::RoutingError.new("tag not found")
|
raise ActionController::RoutingError.new("tag not found")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class SignupController < ApplicationController
|
class SignupController < ApplicationController
|
||||||
def index
|
def index
|
||||||
@title = "Signup"
|
@page_title = "Signup"
|
||||||
@new_user = User.new
|
@new_user = User.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,46 +14,4 @@ class SignupController < ApplicationController
|
||||||
render :action => "index"
|
render :action => "index"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# public function verify() {
|
|
||||||
# if ($_SESSION["random_hash"] == "")
|
|
||||||
# return $this->redirect_to("/signup?nocookies=1");
|
|
||||||
#
|
|
||||||
# $this->page_title = "Signup";
|
|
||||||
#
|
|
||||||
# $this->new_user = new User($this->params["user"]);
|
|
||||||
# $this->new_user->username = $this->new_user->username;
|
|
||||||
# if ($this->new_user->is_valid()) {
|
|
||||||
# $error = false;
|
|
||||||
# try {
|
|
||||||
# $html = Utils::fetch_url("http://news.ycombinator.com/user?id="
|
|
||||||
# . $this->new_user->username);
|
|
||||||
# } catch (Exception $e) {
|
|
||||||
# $error = true;
|
|
||||||
# error_log("error fetching profile for "
|
|
||||||
# . $this->new_user->username . ": " . $e->getMessage());
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# if ($error) {
|
|
||||||
# $this->add_flash_error("Your Hacker News profile could "
|
|
||||||
# . "not be fetched at this time. Please try again "
|
|
||||||
# . "later.");
|
|
||||||
# return $this->render(array("action" => "index"));
|
|
||||||
# } elseif (strpos($html, $_SESSION["random_hash"])) {
|
|
||||||
# $this->new_user->save();
|
|
||||||
#
|
|
||||||
# $this->add_flash_notice("Account created and verified. "
|
|
||||||
# . "Welcome!");
|
|
||||||
# $_SESSION["user_id"] = $this->new_user->id;
|
|
||||||
# return $this->redirect_to("/");
|
|
||||||
# } else {
|
|
||||||
# $this->add_flash_error("Your Hacker News profile did not "
|
|
||||||
# . "contain the string provided below. Verify that "
|
|
||||||
# . "you have cookies enabled and that your Hacker News "
|
|
||||||
# . "profile has been saved after adding the string.");
|
|
||||||
# return $this->render(array("action" => "index"));
|
|
||||||
# }
|
|
||||||
# } else
|
|
||||||
# return $this->render(array("action" => "index"));
|
|
||||||
# }
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,8 @@ class StoriesController < ApplicationController
|
||||||
Vote.vote_thusly_on_story_or_comment_for_user_because(1,
|
Vote.vote_thusly_on_story_or_comment_for_user_because(1,
|
||||||
@story.already_posted_story.id, nil, @user.id, nil)
|
@story.already_posted_story.id, nil, @user.id, nil)
|
||||||
|
|
||||||
|
flash[:error] = "This URL has already been submitted recently"
|
||||||
|
|
||||||
return redirect_to @story.already_posted_story.comments_url
|
return redirect_to @story.already_posted_story.comments_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,6 +43,11 @@ class StoriesController < ApplicationController
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@page_title = "Edit Story"
|
@page_title = "Edit Story"
|
||||||
|
|
||||||
|
if !@story.is_editable_by_user?(@user)
|
||||||
|
flash[:error] = "You cannot edit that story"
|
||||||
|
return redirect_to "/"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_url_title
|
def fetch_url_title
|
||||||
|
@ -81,7 +88,8 @@ class StoriesController < ApplicationController
|
||||||
|
|
||||||
@page_title = @story.title
|
@page_title = @story.title
|
||||||
|
|
||||||
@comments = @story.comments_in_order_for_user(@user ? @user.id : nil)
|
@comments = Comment.ordered_for_story_or_thread_for_user(
|
||||||
|
@story.id, nil, @user ? @user.id : nil)
|
||||||
@comment = Comment.new
|
@comment = Comment.new
|
||||||
|
|
||||||
if @user
|
if @user
|
||||||
|
|
|
@ -1,51 +1,8 @@
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
# function settings() {
|
def show
|
||||||
# if (!$this->user) {
|
@showing_user = User.find_by_username!(params[:id])
|
||||||
# $this->add_flash_error("You must be logged in to edit your "
|
|
||||||
# . "settings.");
|
@page_title = "User: #{@showing_user.username}"
|
||||||
# return $this->redirect_to("/login");
|
|
||||||
# }
|
end
|
||||||
#
|
|
||||||
# $this->page_title = "Edit Settings";
|
|
||||||
#
|
|
||||||
# $this->showing_user = clone $this->user;
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# function show() {
|
|
||||||
# if (!($this->showing_user = User::find_by_username($this->params["id"]))) {
|
|
||||||
# $this->add_flash_error("Could not find user.");
|
|
||||||
# return $this->redirect_to("/");
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# $this->page_title = "User " . $this->showing_user->username;
|
|
||||||
#
|
|
||||||
# if (!$this->params["_s"])
|
|
||||||
# $this->params["_s"] = NULL;
|
|
||||||
#
|
|
||||||
# $this->items = Item::column_sorter($this->params["_s"]);
|
|
||||||
# $this->items->find("all",
|
|
||||||
# array("conditions" => array("user_id = ? AND is_expired = 0",
|
|
||||||
# $this->showing_user->id),
|
|
||||||
# "include" => array("user", "item_kind"),
|
|
||||||
# "joins" => array("user")));
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# function update() {
|
|
||||||
# if (!$this->user) {
|
|
||||||
# $this->add_flash_error("You must be logged in to edit your "
|
|
||||||
# . "settings.");
|
|
||||||
# return $this->redirect_to("/login");
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# $this->page_title = "Edit Settings";
|
|
||||||
#
|
|
||||||
# $this->showing_user = clone $this->user;
|
|
||||||
#
|
|
||||||
# if ($this->showing_user->update_attributes($this->params["user"])) {
|
|
||||||
# $this->add_flash_notice("Your settings have been updated.");
|
|
||||||
# return $this->redirect_to(array("controller" => "users",
|
|
||||||
# "action" => "settings"));
|
|
||||||
# } else
|
|
||||||
# return $this->render(array("action" => "settings"));
|
|
||||||
# }
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,8 @@ class Comment < ActiveRecord::Base
|
||||||
after_create :assign_votes
|
after_create :assign_votes
|
||||||
after_destroy :unassign_votes
|
after_destroy :unassign_votes
|
||||||
|
|
||||||
|
MAX_EDIT_MINS = 45
|
||||||
|
|
||||||
validate do
|
validate do
|
||||||
self.comment.to_s.strip == "" &&
|
self.comment.to_s.strip == "" &&
|
||||||
errors.add(:comment, "cannot be blank.")
|
errors.add(:comment, "cannot be blank.")
|
||||||
|
@ -85,4 +87,44 @@ class Comment < ActiveRecord::Base
|
||||||
def flag!
|
def flag!
|
||||||
Story.update_counters self.id, :flaggings => 1
|
Story.update_counters self.id, :flaggings => 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.ordered_for_story_or_thread_for_user(story_id, thread_id, user_id)
|
||||||
|
parents = {}
|
||||||
|
|
||||||
|
if thread_id
|
||||||
|
cs = [ "thread_id = ?", thread_id ]
|
||||||
|
else
|
||||||
|
cs = [ "story_id = ?", story_id ]
|
||||||
|
end
|
||||||
|
|
||||||
|
Comment.find(:all, :conditions => cs).sort_by{|c| c.confidence }.each do |c|
|
||||||
|
(parents[c.parent_comment_id.to_i] ||= []).push c
|
||||||
|
end
|
||||||
|
|
||||||
|
# top-down list of comments, regardless of indent level
|
||||||
|
ordered = []
|
||||||
|
|
||||||
|
recursor = lambda{|comment,level|
|
||||||
|
if comment
|
||||||
|
comment.indent_level = level
|
||||||
|
ordered.push comment
|
||||||
|
end
|
||||||
|
|
||||||
|
# for each comment that is a child of this one, recurse with it
|
||||||
|
(parents[comment ? comment.id : 0] || []).each do |child|
|
||||||
|
recursor.call(child, level + 1)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
recursor.call(nil, 0)
|
||||||
|
|
||||||
|
ordered
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_editable_by_user?(user)
|
||||||
|
if !user || user.id != self.user_id
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
(Time.now.to_i - self.created_at.to_i < (60 * MAX_EDIT_MINS))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,9 +21,9 @@ class Keystore < ActiveRecord::Base
|
||||||
def self.incremented_value_for(key, amount = 1)
|
def self.incremented_value_for(key, amount = 1)
|
||||||
new_value = nil
|
new_value = nil
|
||||||
|
|
||||||
Keystore.connection.execute([ "INSERT INTO #{Keystore.table_name} (" +
|
Keystore.connection.execute("INSERT INTO #{Keystore.table_name} (" +
|
||||||
"`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `count` = " +
|
"`key`, `value`) VALUES (#{q(key)}, #{q(amount)}) ON DUPLICATE KEY " +
|
||||||
"`count` + ?", key, amount, amount ])
|
"UPDATE `value` = `value` + #{q(amount)}")
|
||||||
|
|
||||||
return self.value_for(key)
|
return self.value_for(key)
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,14 +13,29 @@ class Story < ActiveRecord::Base
|
||||||
attr_accessible :url, :title, :description, :story_type, :tags_a
|
attr_accessible :url, :title, :description, :story_type, :tags_a
|
||||||
|
|
||||||
# after this many minutes old, a story cannot be edited
|
# after this many minutes old, a story cannot be edited
|
||||||
MAX_EDIT_MINS = 9999 # XXX 15
|
MAX_EDIT_MINS = 30
|
||||||
|
|
||||||
attr_accessor :vote, :story_type, :already_posted_story
|
attr_accessor :vote, :story_type, :already_posted_story
|
||||||
attr_accessor :tags_to_add, :tags_to_delete
|
attr_accessor :tags_to_add, :tags_to_delete
|
||||||
|
|
||||||
after_save :deal_with_tags
|
after_save :deal_with_tags
|
||||||
before_create :assign_short_id
|
before_create :assign_short_id
|
||||||
before_create :find_duplicate
|
|
||||||
|
validate do
|
||||||
|
if self.url.present?
|
||||||
|
# URI.parse is not very lenient, so we can't use it
|
||||||
|
|
||||||
|
if self.url.match(/\Ahttps?:\/\/[^\.]+\.[a-z]+\//)
|
||||||
|
if (s = Story.find_by_url(self.url)) &&
|
||||||
|
(Time.now - s.created_at) < 30.days
|
||||||
|
errors.add(:url, "has already been submitted recently")
|
||||||
|
self.already_posted_story = s
|
||||||
|
end
|
||||||
|
else
|
||||||
|
errors.add(:url, "is not valid")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def assign_short_id
|
def assign_short_id
|
||||||
(1...10).each do |tries|
|
(1...10).each do |tries|
|
||||||
|
@ -35,14 +50,6 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_duplicate
|
|
||||||
if (s = Story.find_by_url(self.url)) &&
|
|
||||||
(Time.now - s.created_at) < 30.days
|
|
||||||
errors.add(:url, "has already been submitted recently")
|
|
||||||
self.already_posted_story = s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def deal_with_tags
|
def deal_with_tags
|
||||||
(self.tags_to_delete || []).each do |t|
|
(self.tags_to_delete || []).each do |t|
|
||||||
if t.is_a?(Tagging)
|
if t.is_a?(Tagging)
|
||||||
|
@ -65,31 +72,6 @@ class Story < ActiveRecord::Base
|
||||||
self.tags_to_add = []
|
self.tags_to_add = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def comments_in_order_for_user(user_id)
|
|
||||||
parents = {}
|
|
||||||
Comment.find_all_by_story_id(self.id).sort_by{|c| c.confidence }.each do |c|
|
|
||||||
(parents[c.parent_comment_id.to_i] ||= []).push c
|
|
||||||
end
|
|
||||||
|
|
||||||
# top-down list of comments, regardless of indent level
|
|
||||||
ordered = []
|
|
||||||
|
|
||||||
recursor = lambda{|comment,level|
|
|
||||||
if comment
|
|
||||||
comment.indent_level = level
|
|
||||||
ordered.push comment
|
|
||||||
end
|
|
||||||
|
|
||||||
# for each comment that is a child of this one, recurse with it
|
|
||||||
(parents[comment ? comment.id : 0] || []).each do |child|
|
|
||||||
recursor.call(child, level + 1)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
recursor.call(nil, 0)
|
|
||||||
|
|
||||||
ordered
|
|
||||||
end
|
|
||||||
|
|
||||||
def comments_url
|
def comments_url
|
||||||
"/p/#{self.short_id}/#{self.title_as_url}"
|
"/p/#{self.short_id}/#{self.title_as_url}"
|
||||||
end
|
end
|
||||||
|
@ -176,7 +158,7 @@ class Story < ActiveRecord::Base
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
true #(Time.now.to_i - self.created_at.to_i < (60 * Story::MAX_EDIT_MINS))
|
(Time.now.to_i - self.created_at.to_i < (60 * MAX_EDIT_MINS))
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_undeletable_by_user?(user)
|
def is_undeletable_by_user?(user)
|
||||||
|
|
|
@ -31,10 +31,28 @@ class User < ActiveRecord::Base
|
||||||
Keystore.value_for("user:#{self.id}:karma").to_i
|
Keystore.value_for("user:#{self.id}:karma").to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stories_submitted_count
|
||||||
|
Keystore.get("user:#{self.id}:stories_submitted").to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def comments_posted_count
|
||||||
|
Keystore.get("user:#{self.id}:comments_posted").to_i
|
||||||
|
end
|
||||||
|
|
||||||
def initiate_password_reset_for_ip(ip)
|
def initiate_password_reset_for_ip(ip)
|
||||||
self.password_reset_token = Utils.random_key(60)
|
self.password_reset_token = Utils.random_key(60)
|
||||||
self.save!
|
self.save!
|
||||||
|
|
||||||
PasswordReset.password_reset_link(self, ip).deliver
|
PasswordReset.password_reset_link(self, ip).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def linkified_about
|
||||||
|
Markdowner.markdown(self.about)
|
||||||
|
end
|
||||||
|
|
||||||
|
def recent_threads(amount = 20)
|
||||||
|
Comment.connection.select_all("SELECT DISTINCT " +
|
||||||
|
"thread_id FROM comments WHERE user_id = #{q(self.id)} ORDER BY " +
|
||||||
|
"created_at DESC LIMIT #{q(amount)}").map{|r| r.values.first }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,9 +97,17 @@ class Vote < ActiveRecord::Base
|
||||||
if v.comment_id
|
if v.comment_id
|
||||||
Comment.update_counters v.comment_id, :downvotes => downvote,
|
Comment.update_counters v.comment_id, :downvotes => downvote,
|
||||||
:upvotes => upvote
|
:upvotes => upvote
|
||||||
|
|
||||||
|
if (c = Comment.find(v.comment_id)) && c.user_id != user_id
|
||||||
|
Keystore.increment_value_for("user:#{c.user_id}:karma")
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Story.update_counters v.story_id, :downvotes => downvote,
|
Story.update_counters v.story_id, :downvotes => downvote,
|
||||||
:upvotes => upvote
|
:upvotes => upvote
|
||||||
|
|
||||||
|
if (s = Story.find(v.story_id)) && s.user_id != user_id
|
||||||
|
Keystore.increment_value_for("user:#{s.user_id}:karma")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,11 +16,13 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
|
||||||
<div class="byline">
|
<div class="byline">
|
||||||
<% if comment.previewing %>
|
<% if comment.previewing %>
|
||||||
<a><%= comment.user.username %></a>
|
<a><%= comment.user.username %></a>
|
||||||
|
previewed
|
||||||
just now
|
just now
|
||||||
<span class="reason">(Preview)</span>
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="/u/<%= comment.user.username %>"><%= comment.user.username
|
<a href="/u/<%= comment.user.username %>"><%= comment.user.username
|
||||||
%></a>
|
%></a>
|
||||||
|
|
||||||
|
<%= comment.updated_at ? "edited" : "" %>
|
||||||
<%= time_ago_in_words(comment.created_at).gsub(/^about /, "") %> ago
|
<%= time_ago_in_words(comment.created_at).gsub(/^about /, "") %> ago
|
||||||
|
|
||||||
<span class="reason"><%= comment.current_vote &&
|
<span class="reason"><%= comment.current_vote &&
|
||||||
|
@ -28,27 +30,32 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
|
||||||
"(#{Vote::COMMENT_REASONS[comment.current_vote[:reason]]})" : ""
|
"(#{Vote::COMMENT_REASONS[comment.current_vote[:reason]]})" : ""
|
||||||
%></span>
|
%></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if !comment.previewing %>
|
||||||
|
|
|
||||||
|
|
||||||
|
<a href="<%= story.comments_url %>/comments/<%= comment.short_id
|
||||||
|
%>">link</a>
|
||||||
|
|
|
||||||
|
<% if comment.is_editable_by_user?(@user) %>
|
||||||
|
<a class="comment_editor">edit</a>
|
||||||
|
<% else %>
|
||||||
|
<a class="comment_replier">reply</a>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if false && defined?(collapsable) && collapsable # XXX %>
|
||||||
|
|
|
||||||
|
<a href="">collapse</a>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if defined?(show_story) && show_story %>
|
||||||
|
| on
|
||||||
|
<a href="<%= story.comments_url %>"><%= story.title %></a>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="comment_text">
|
<div class="comment_text">
|
||||||
<%= raw comment.linkified_comment %>
|
<%= raw comment.linkified_comment %>
|
||||||
|
|
||||||
<div class="comment_actions">
|
|
||||||
<% if comment.previewing %>
|
|
||||||
<a>link</a>
|
|
||||||
|
|
||||||
<a>reply</a>
|
|
||||||
<% else %>
|
|
||||||
<a href="<%= story.comments_url %>/comments/<%= comment.short_id
|
|
||||||
%>">link</a>
|
|
||||||
|
|
||||||
<a class="comment_replier">reply</a>
|
|
||||||
|
|
||||||
<% if defined?(collapsable) && collapsable %>
|
|
||||||
|
|
||||||
<a href="">collapse</a>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="comment_reply"></div>
|
<div class="comment_reply"></div>
|
|
@ -33,7 +33,7 @@
|
||||||
<% if defined?(show_comment) %>
|
<% if defined?(show_comment) %>
|
||||||
<% if show_comment.valid? %>
|
<% if show_comment.valid? %>
|
||||||
<ol class="comments comments1 preview">
|
<ol class="comments comments1 preview">
|
||||||
<%= render :partial => "stories/comment",
|
<%= render :partial => "comments/comment",
|
||||||
:locals => { :comment => show_comment, :story => story } %>
|
:locals => { :comment => show_comment, :story => story } %>
|
||||||
</ol>
|
</ol>
|
||||||
<% else %>
|
<% else %>
|
4
app/views/comments/_postedreply.html.erb
Normal file
4
app/views/comments/_postedreply.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<ol class="comments comments1 preview">
|
||||||
|
<%= render :partial => "comments/comment",
|
||||||
|
:locals => { :comment => show_comment, :story => story } %>
|
||||||
|
</ol>
|
23
app/views/comments/threads.html.erb
Normal file
23
app/views/comments/threads.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<% cur_story = nil %>
|
||||||
|
<% indent_level = -1 %>
|
||||||
|
<% @comments.each_with_index do |comment,x| %>
|
||||||
|
<% if !cur_story || comment.story_id != cur_story.id %>
|
||||||
|
<% cur_story = Story.find(comment.story_id) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if comment.indent_level > indent_level %>
|
||||||
|
<ol class="comments comments<%= comment.indent_level %>">
|
||||||
|
<% elsif comment.indent_level < indent_level %>
|
||||||
|
<% (indent_level - comment.indent_level).times do %>
|
||||||
|
</ol>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= render :partial => "comments/comment", :locals => { :story => cur_story,
|
||||||
|
:comment => comment, :show_story => (comment.indent_level == 1) } %>
|
||||||
|
|
||||||
|
<% indent_level = comment.indent_level %>
|
||||||
|
<% end %>
|
||||||
|
<% indent_level.times do %>
|
||||||
|
</ol>
|
||||||
|
<% end %>
|
|
@ -1,14 +1,17 @@
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<div id="headerright" class="<%= @user ? "loggedin" : "" %>">
|
<div id="headerright" class="<%= @user ? "loggedin" : "" %>">
|
||||||
<% if @user %>
|
<% if @user %>
|
||||||
<a href="/users/<%= @user.username %>"><%= @user.username
|
<a href="/u/<%= @user.username %>"><%= @user.username
|
||||||
%> (<%= @user.karma %>)</a>
|
%> (<%= @user.karma %>)</a>
|
||||||
|
|
||||||
|
<% if false %>
|
||||||
<% if (count = @user.unread_message_count) > 0 %>
|
<% if (count = @user.unread_message_count) > 0 %>
|
||||||
<a href="/messages"><%= count %> New Message<%= count == 1 ? "" : "s"
|
<a href="/messages"><%= count %> New Message<%= count == 1 ? "" : "s"
|
||||||
%></a>
|
%></a>
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="/messages">Messages</a>
|
<a href="/messages">Messages</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<%= link_to "Logout", { :controller => "login", :action => "logout" },
|
<%= link_to "Logout", { :controller => "login", :action => "logout" },
|
||||||
{ :confirm => "Are you sure you want to logout?",
|
{ :confirm => "Are you sure you want to logout?",
|
||||||
"method" => "post" } %>
|
"method" => "post" } %>
|
||||||
|
@ -36,7 +39,7 @@
|
||||||
<% if @user %>
|
<% if @user %>
|
||||||
<a href="/threads">Your Threads</a>
|
<a href="/threads">Your Threads</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<a href="/stories/new">Submit</a>
|
<a href="/stories/new">Submit Story</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
<% if flash[:error] %>
|
|
||||||
<div class="flash-error"><%= flash[:error] %></div>
|
|
||||||
<% elsif flash[:success] %>
|
|
||||||
<div class="flash-success"><%= flash[:success] %></div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<ol class="stories list">
|
<ol class="stories list">
|
||||||
<%= render :partial => "stories/listdetail", :collection => @stories,
|
<%= render :partial => "stories/listdetail", :collection => @stories,
|
||||||
:as => :story %>
|
:as => :story %>
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
<%= render :partial => "global/header" %>
|
<%= render :partial => "global/header" %>
|
||||||
|
|
||||||
<div id="inside">
|
<div id="inside">
|
||||||
|
<% if flash[:error] %>
|
||||||
|
<div class="flash-error"><%= flash[:error] %></div>
|
||||||
|
<% elsif flash[:success] %>
|
||||||
|
<div class="flash-success"><%= flash[:success] %></div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="box">
|
<div class="box wide">
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
Reset Password
|
Reset Password
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,10 +9,6 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<%= form_tag reset_password_url do %>
|
<%= form_tag reset_password_url do %>
|
||||||
<% if flash[:error] %>
|
|
||||||
<div class="flash-error"><%= flash[:error] %></div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= label_tag :email, "E-mail or Username:" %>
|
<%= label_tag :email, "E-mail or Username:" %>
|
||||||
<%= text_field_tag :email, "", :size => 30 %>
|
<%= text_field_tag :email, "", :size => 30 %>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= form_tag login_url do %>
|
<%= form_tag login_url do %>
|
||||||
<% if flash[:error] %>
|
|
||||||
<div class="flash-error"><%= flash[:error] %></div>
|
|
||||||
<% elsif flash[:success] %>
|
|
||||||
<div class="flash-success"><%= flash[:success] %></div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= label_tag :email, "E-mail or Username:" %>
|
<%= label_tag :email, "E-mail or Username:" %>
|
||||||
<%= text_field_tag :email, "", :size => 30 %>
|
<%= text_field_tag :email, "", :size => 30 %>
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<div class="box">
|
<div class="box wide">
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
Set New Password
|
Set New Password
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= form_tag set_new_password_url, { :autocomplete => "off" } do %>
|
<%= form_tag set_new_password_url, { :autocomplete => "off" } do %>
|
||||||
<% if flash[:error] %>
|
|
||||||
<div class="flash-error"><%= flash[:error] %></div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= error_messages_for(@reset_user) %>
|
<%= error_messages_for(@reset_user) %>
|
||||||
|
|
||||||
<%= hidden_field_tag "token", params[:token] %>
|
<%= hidden_field_tag "token", params[:token] %>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="box">
|
<div class="box wide">
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
Create an Account
|
Create an Account
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
<% if @user && !@story.is_expired? %>
|
<% if @user && !@story.is_expired? %>
|
||||||
<%= render :partial => "stories/commentbox",
|
<%= render :partial => "comments/commentbox",
|
||||||
:locals => { :story => @story, :comment => @comment } %>
|
:locals => { :story => @story, :comment => @comment } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render :partial => "stories/comment", :locals => { :story => @story,
|
<%= render :partial => "comments/comment", :locals => { :story => @story,
|
||||||
:comment => comment, :collapsable => (@comments[x + 1].
|
:comment => comment, :collapsable => (@comments[x + 1].
|
||||||
try(:parent_comment_id).to_i == comment.id) } %>
|
try(:parent_comment_id).to_i == comment.id) } %>
|
||||||
|
|
||||||
|
|
42
app/views/users/show.html.erb
Normal file
42
app/views/users/show.html.erb
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<div class="box wide">
|
||||||
|
<div class="legend">
|
||||||
|
<%= @showing_user.username %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="required">Status:</label>
|
||||||
|
<span class="d">
|
||||||
|
Active <%= @showing_user.is_admin? ? "administrator" : "user" %>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label class="required">Joined:</label>
|
||||||
|
<span class="d">
|
||||||
|
<%= time_ago_in_words(@user.created_at) %> ago
|
||||||
|
(<%= @user.created_at.strftime("%Y-%m-%d") %>)
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label class="required">Karma:</label>
|
||||||
|
<span class="d">
|
||||||
|
<%= @showing_user.karma %>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label class="required">Stories Submitted:</label>
|
||||||
|
<span class="d">
|
||||||
|
<%= @showing_user.stories_submitted_count %>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label class="required">Comments Posted:</label>
|
||||||
|
<span class="d">
|
||||||
|
<%= Keystore.get("user:#{@showing_user.id}:comments_posted").to_i %>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label class="required">About:</label>
|
||||||
|
<span class="d">
|
||||||
|
<%= @user.linkified_about %>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
</div>
|
|
@ -1,12 +1,16 @@
|
||||||
Lobsters::Application.routes.draw do
|
Lobsters::Application.routes.draw do
|
||||||
root :to => "home#index"
|
root :to => "home#index"
|
||||||
|
|
||||||
get "login" => "login#index"
|
get "/newest" => "home#newest"
|
||||||
post "login" => "login#login"
|
|
||||||
post "logout" => "login#logout"
|
|
||||||
|
|
||||||
get "signup" => "signup#index"
|
get "/threads" => "comments#threads"
|
||||||
post "signup" => "signup#signup"
|
|
||||||
|
get "/login" => "login#index"
|
||||||
|
post "/login" => "login#login"
|
||||||
|
post "/logout" => "login#logout"
|
||||||
|
|
||||||
|
get "/signup" => "signup#index"
|
||||||
|
post "/signup" => "signup#signup"
|
||||||
|
|
||||||
match "/login/forgot_password" => "login#forgot_password",
|
match "/login/forgot_password" => "login#forgot_password",
|
||||||
:as => "forgot_password"
|
:as => "forgot_password"
|
||||||
|
@ -34,4 +38,5 @@ Lobsters::Application.routes.draw do
|
||||||
post "/comments/preview/:story_id" => "comments#preview"
|
post "/comments/preview/:story_id" => "comments#preview"
|
||||||
|
|
||||||
get "/p/:id/(:title)" => "stories#show"
|
get "/p/:id/(:title)" => "stories#show"
|
||||||
|
get "/u/:id" => "users#show"
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Markdowner
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.markdown(string)
|
def self.markdown(string)
|
||||||
lines = string.rstrip.split(/\r?\n/)
|
lines = string.to_s.rstrip.split(/\r?\n/)
|
||||||
|
|
||||||
out = "<p>"
|
out = "<p>"
|
||||||
inpre = false
|
inpre = false
|
||||||
|
|
Loading…
Reference in a new issue