Rather than keep "poorly titled" and "poorly tagged" as reasons for flagging, make the user do the work of suggesting new ones. At some point, suggested taggings will flip to real taggings once they reach a certain count (to be determined later). This also has to take into account tagging sets that don't contain current tags, for when they need to be removed. For titles, I'm not yet sure how to handle this in an automated fashion except for the (probably rare) case of multiple users submitting the same exact thing, but at least collect them for now. Issue #207
361 lines
8.8 KiB
Ruby
361 lines
8.8 KiB
Ruby
class StoriesController < ApplicationController
|
|
before_filter :require_logged_in_user_or_400,
|
|
:only => [ :upvote, :downvote, :unvote, :hide, :unhide, :preview ]
|
|
before_filter :require_logged_in_user, :only => [ :destroy, :create, :edit,
|
|
:fetch_url_title, :new, :suggest ]
|
|
before_filter :find_user_story, :only => [ :destroy, :edit, :undelete,
|
|
:update ]
|
|
before_filter :find_story!, :only => [ :suggest, :submit_suggestions ]
|
|
|
|
def create
|
|
@title = "Submit Story"
|
|
@cur_url = "/stories/new"
|
|
|
|
@story = Story.new(story_params)
|
|
@story.user_id = @user.id
|
|
|
|
if @story.valid? && !(@story.already_posted_story && !@story.seen_previous)
|
|
if @story.save
|
|
Countinual.count!("#{Rails.application.shortname}.stories.submitted",
|
|
"+1")
|
|
|
|
return redirect_to @story.comments_path
|
|
end
|
|
end
|
|
|
|
return render :action => "new"
|
|
end
|
|
|
|
def destroy
|
|
if !@story.is_editable_by_user?(@user)
|
|
flash[:error] = "You cannot edit that story."
|
|
return redirect_to "/"
|
|
end
|
|
|
|
@story.is_expired = true
|
|
@story.editor = @user
|
|
|
|
if params[:reason].present? && @story.user_id != @user.id
|
|
@story.moderation_reason = params[:reason]
|
|
end
|
|
|
|
@story.save(:validate => false)
|
|
|
|
redirect_to @story.comments_path
|
|
end
|
|
|
|
def edit
|
|
if !@story.is_editable_by_user?(@user)
|
|
flash[:error] = "You cannot edit that story."
|
|
return redirect_to "/"
|
|
end
|
|
|
|
@title = "Edit Story"
|
|
|
|
if @story.merged_into_story
|
|
@story.merge_story_short_id = @story.merged_into_story.short_id
|
|
end
|
|
end
|
|
|
|
def fetch_url_attributes
|
|
s = Story.new
|
|
s.fetching_ip = request.remote_ip
|
|
s.url = params[:fetch_url]
|
|
|
|
oattrs = { :url => params[:fetch_url], :title => nil }
|
|
|
|
if (title = s.fetched_title).present?
|
|
oattrs[:title] = title
|
|
end
|
|
|
|
if (cu = s.fetched_canonical_url).present?
|
|
oattrs[:url] = cu
|
|
end
|
|
|
|
return render :json => oattrs
|
|
end
|
|
|
|
def new
|
|
@title = "Submit Story"
|
|
@cur_url = "/stories/new"
|
|
|
|
@story = Story.new
|
|
@story.fetching_ip = request.remote_ip
|
|
|
|
if params[:url].present?
|
|
@story.url = params[:url]
|
|
|
|
if (cu = @story.fetched_canonical_url).present? && @story.url != cu
|
|
flash.now[:notice] = "Note: URL has been changed to fetched " <<
|
|
"canonicalized version"
|
|
@story.url = cu
|
|
end
|
|
|
|
if s = Story.find_similar_by_url(@story.url)
|
|
if s.is_recent?
|
|
# user won't be able to submit this story as new, so just redirect
|
|
# them to the previous story
|
|
flash[:success] = "This URL has already been submitted recently."
|
|
return redirect_to s.comments_path
|
|
else
|
|
# user will see a warning like with preview screen
|
|
@story.already_posted_story = s
|
|
end
|
|
end
|
|
|
|
# ignore what the user brought unless we need it as a fallback
|
|
@story.title = @story.fetched_title
|
|
if !@story.title.present? && params[:title].present?
|
|
@story.title = params[:title]
|
|
end
|
|
end
|
|
end
|
|
|
|
def preview
|
|
@story = Story.new(story_params)
|
|
@story.user_id = @user.id
|
|
@story.previewing = true
|
|
|
|
@story.vote = Vote.new(:vote => 1)
|
|
@story.upvotes = 1
|
|
|
|
@story.valid?
|
|
|
|
@story.seen_previous = true
|
|
|
|
return render :action => "new", :layout => false
|
|
end
|
|
|
|
def show
|
|
@story = Story.where(:short_id => params[:id]).first!
|
|
|
|
if @story.merged_into_story
|
|
flash[:success] = "\"#{@story.title}\" has been merged into this story."
|
|
return redirect_to @story.merged_into_story.comments_path
|
|
end
|
|
|
|
if @story.can_be_seen_by_user?(@user)
|
|
@title = @story.title
|
|
else
|
|
@title = "[Story removed]"
|
|
end
|
|
|
|
@short_url = @story.short_id_url
|
|
|
|
@comments = @story.merged_comments.includes(:user, :story,
|
|
:hat).arrange_for_user(@user)
|
|
|
|
if params[:comment_short_id]
|
|
@comments.each do |c,x|
|
|
if c.short_id == params[:comment_short_id]
|
|
c.highlighted = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
respond_to do |format|
|
|
format.html {
|
|
@comment = @story.comments.build
|
|
|
|
load_user_votes
|
|
|
|
render :action => "show"
|
|
}
|
|
format.json {
|
|
render :json => @story.as_json(:with_comments => @comments)
|
|
}
|
|
end
|
|
end
|
|
|
|
def suggest
|
|
if (st = @story.suggested_taggings.where(:user_id => @user.id)).any?
|
|
@story.tags_a = st.map{|st| st.tag.tag }
|
|
end
|
|
if tt = @story.suggested_titles.where(:user_id => @user.id).first
|
|
@story.title = tt.title
|
|
end
|
|
end
|
|
|
|
def submit_suggestions
|
|
ostory = @story.dup
|
|
|
|
@story.title = params[:story][:title]
|
|
if @story.valid?
|
|
if @story.title != ostory.title
|
|
@story.save_suggested_title_for_user!(@story.title, @user)
|
|
end
|
|
if @story.tags_a.sort != params[:story][:tags_a].sort
|
|
@story.save_suggested_tags_a_for_user!(params[:story][:tags_a], @user)
|
|
end
|
|
flash[:success] = "Your suggested changes have been noted."
|
|
redirect_to ostory.comments_path
|
|
else
|
|
render :action => "suggest"
|
|
end
|
|
end
|
|
|
|
def undelete
|
|
if !(@story.is_editable_by_user?(@user) &&
|
|
@story.is_undeletable_by_user?(@user))
|
|
flash[:error] = "You cannot edit that story."
|
|
return redirect_to "/"
|
|
end
|
|
|
|
@story.is_expired = false
|
|
@story.editor = @user
|
|
@story.save(:validate => false)
|
|
|
|
redirect_to @story.comments_path
|
|
end
|
|
|
|
def update
|
|
if !@story.is_editable_by_user?(@user)
|
|
flash[:error] = "You cannot edit that story."
|
|
return redirect_to "/"
|
|
end
|
|
|
|
@story.is_expired = false
|
|
@story.editor = @user
|
|
|
|
if @story.url_is_editable_by_user?(@user)
|
|
@story.attributes = story_params
|
|
else
|
|
@story.attributes = story_params.except(:url)
|
|
end
|
|
|
|
if @story.save
|
|
return redirect_to @story.comments_path
|
|
else
|
|
return render :action => "edit"
|
|
end
|
|
end
|
|
|
|
def unvote
|
|
if !(story = find_story)
|
|
return render :text => "can't find story", :status => 400
|
|
end
|
|
|
|
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
|
|
nil, @user.id, nil)
|
|
|
|
render :text => "ok"
|
|
end
|
|
|
|
def upvote
|
|
if !(story = find_story)
|
|
return render :text => "can't find story", :status => 400
|
|
end
|
|
|
|
Vote.vote_thusly_on_story_or_comment_for_user_because(1, story.id,
|
|
nil, @user.id, nil)
|
|
|
|
render :text => "ok"
|
|
end
|
|
|
|
def downvote
|
|
if !(story = find_story)
|
|
return render :text => "can't find story", :status => 400
|
|
end
|
|
|
|
if !Vote::STORY_REASONS[params[:reason]]
|
|
return render :text => "invalid reason", :status => 400
|
|
end
|
|
|
|
if !@user.can_downvote?(story)
|
|
return render :text => "not permitted to downvote", :status => 400
|
|
end
|
|
|
|
Vote.vote_thusly_on_story_or_comment_for_user_because(-1, story.id,
|
|
nil, @user.id, params[:reason])
|
|
|
|
render :text => "ok"
|
|
end
|
|
|
|
def hide
|
|
if !(story = find_story)
|
|
return render :text => "can't find story", :status => 400
|
|
end
|
|
|
|
HiddenStory.hide_story_for_user(story.id, @user.id)
|
|
|
|
render :text => "ok"
|
|
end
|
|
|
|
def unhide
|
|
if !(story = find_story)
|
|
return render :text => "can't find story", :status => 400
|
|
end
|
|
|
|
HiddenStory.where(:user_id => @user.id, :story_id => story.id).delete_all
|
|
|
|
render :text => "ok"
|
|
end
|
|
|
|
private
|
|
|
|
def story_params
|
|
p = params.require(:story).permit(
|
|
:title, :url, :description, :moderation_reason, :seen_previous,
|
|
:merge_story_short_id, :is_unavailable, :user_is_author, :tags_a => [],
|
|
)
|
|
|
|
if @user.is_moderator?
|
|
p
|
|
else
|
|
p.except(:moderation_reason, :merge_story_short_id, :is_unavailable)
|
|
end
|
|
end
|
|
|
|
def find_story
|
|
story = Story.where(:short_id => params[:story_id]).first
|
|
if @user && story
|
|
story.vote = Vote.where(:user_id => @user.id,
|
|
:story_id => story.id, :comment_id => nil).first.try(:vote)
|
|
end
|
|
|
|
story
|
|
end
|
|
|
|
def find_story!
|
|
@story = find_story
|
|
if !@story
|
|
raise ActiveRecord::RecordNotFound
|
|
end
|
|
end
|
|
|
|
def find_user_story
|
|
if @user.is_moderator?
|
|
@story = Story.where(:short_id => params[:story_id] || params[:id]).first
|
|
else
|
|
@story = Story.where(:user_id => @user.id, :short_id =>
|
|
(params[:story_id] || params[:id])).first
|
|
end
|
|
|
|
if !@story
|
|
flash[:error] = "Could not find story or you are not authorized " <<
|
|
"to manage it."
|
|
redirect_to "/"
|
|
return false
|
|
end
|
|
end
|
|
|
|
def load_user_votes
|
|
if @user
|
|
if v = Vote.where(:user_id => @user.id, :story_id => @story.id,
|
|
:comment_id => nil).first
|
|
@story.vote = { :vote => v.vote, :reason => v.reason }
|
|
end
|
|
|
|
@story.is_hidden_by_cur_user = @story.is_hidden_by_user?(@user)
|
|
|
|
@votes = Vote.comment_votes_by_user_for_story_hash(@user.id, @story.id)
|
|
@comments.each do |c|
|
|
if @votes[c.id]
|
|
c.current_vote = @votes[c.id]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|