-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add multi-reply feature #2378
base: main
Are you sure you want to change the base?
Add multi-reply feature #2378
Changes from 38 commits
ed4b809
4ad23aa
d538f97
bb7edd3
8726ce9
60dba60
f2c8aa5
0d915c3
58b9a9a
4e54524
d3c8dbc
06b19e3
d8ac6f1
98044f2
3f7daee
5f5587d
ef048e3
33cbcf3
065ab1e
27759de
7d4741b
4c911ef
0341967
8e2b16a
921ca6b
2462f5f
a68e988
e08b2b7
9388e86
aac9700
af2a413
994bd8a
ccd2de5
236f18d
c5256c4
c1a4114
479dfc1
6652047
d1987b6
80d59e6
9947167
1562e1b
24388da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
class RepliesController < WritableController | ||
before_action :login_required, except: [:search, :show, :history] | ||
before_action :get_multi_replies, only: [:create, :update] | ||
before_action :find_model, only: [:show, :history, :edit, :update, :destroy] | ||
before_action :editor_setup, only: [:edit] | ||
before_action :require_create_permission, only: [:create] | ||
|
@@ -116,7 +117,24 @@ def create | |
redirect_to post_path(post_id, page: :unread, anchor: :unread) and return | ||
elsif params[:button_preview] | ||
draft = make_draft | ||
preview(ReplyDraft.reply_from_draft(draft)) and return | ||
preview_reply(ReplyDraft.reply_from_draft(draft)) and return | ||
elsif params[:button_submit_previewed_multi_reply] | ||
if editing_multi_reply? | ||
edit_reply(true) | ||
else | ||
post_replies | ||
end | ||
return | ||
elsif params[:button_discard_multi_reply] | ||
flash[:success] = "Replies discarded." | ||
if editing_multi_reply? | ||
# Editing multi reply, going to redirect back to the reply I'm editing | ||
redirect_to reply_path(@reply, anchor: "reply-#{@reply.id}") | ||
else | ||
# Posting a new multi reply, go back to unread | ||
redirect_to post_path(params[:reply][:post_id], page: :unread, anchor: :unread) | ||
end | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid too many There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried reducing them as much as I could but I don't think I can do better than what I currently have. |
||
end | ||
|
||
reply = Reply.new(permitted_params) | ||
|
@@ -139,10 +157,10 @@ def create | |
flash.now[:error] = "This looks like a duplicate. Did you attempt to post this twice? Please resubmit if this was intentional." | ||
@allow_dupe = true | ||
if most_recent_unseen_reply.nil? || (most_recent_unseen_reply.id == last_by_user.id && @unseen_replies.count == 1) | ||
preview(reply) | ||
preview_reply(reply) | ||
else | ||
draft = make_draft(false) | ||
preview(ReplyDraft.reply_from_draft(draft)) | ||
preview_reply(ReplyDraft.reply_from_draft(draft)) | ||
end | ||
return | ||
end | ||
|
@@ -154,20 +172,17 @@ def create | |
pluraled = num > 1 ? "have been #{num} new replies" : "has been 1 new reply" | ||
flash.now[:error] = "There #{pluraled} since you last viewed this post." | ||
draft = make_draft | ||
preview(ReplyDraft.reply_from_draft(draft)) and return | ||
preview_reply(ReplyDraft.reply_from_draft(draft)) and return | ||
redmvc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
end | ||
|
||
begin | ||
reply.save! | ||
rescue ActiveRecord::RecordInvalid => e | ||
render_errors(reply, action: 'created', now: true, err: e) | ||
|
||
redirect_to posts_path and return unless reply.post | ||
redirect_to post_path(reply.post) | ||
if params[:button_add_more] | ||
# If they click "Add More", fetch the existing array of multi replies if present and add the current permitted_params to that list | ||
add_to_multi_reply(reply, permitted_params) | ||
elsif editing_multi_reply? | ||
edit_reply(true, new_multi_reply: reply) | ||
else | ||
flash[:success] = "Reply posted." | ||
redirect_to reply_path(reply, anchor: "reply-#{reply.id}") | ||
post_replies(new_reply: reply) | ||
end | ||
end | ||
|
||
|
@@ -187,26 +202,20 @@ def edit | |
def update | ||
@reply.assign_attributes(permitted_params) | ||
process_npc(@reply, permitted_character_params) | ||
preview(@reply) and return if params[:button_preview] | ||
if params[:button_preview] | ||
preview_reply(@reply) and return | ||
elsif params[:button_add_more] | ||
# This will take us to reply create instead, but this reply's ID will be saved | ||
add_to_multi_reply(@reply, permitted_params) and return | ||
end | ||
|
||
if current_user.id != @reply.user_id && @reply.audit_comment.blank? | ||
flash[:error] = "You must provide a reason for your moderator edit." | ||
editor_setup | ||
render :edit and return | ||
end | ||
|
||
begin | ||
@reply.save! | ||
rescue ActiveRecord::RecordInvalid => e | ||
render_errors(@reply, action: 'updated', now: true, err: e) | ||
|
||
@audits = { @reply.id => @post.audits.count } | ||
editor_setup | ||
render :edit | ||
else | ||
flash[:success] = "Reply updated." | ||
redirect_to reply_path(@reply, anchor: "reply-#{@reply.id}") | ||
end | ||
edit_reply(false) | ||
end | ||
|
||
def destroy | ||
|
@@ -297,19 +306,152 @@ def require_edit_permission | |
redirect_to post_path(@reply.post) | ||
end | ||
|
||
def preview(written) | ||
@written = written | ||
@post = @written.post | ||
def get_multi_replies | ||
# Get the multi replies stored in the page JSON | ||
@multi_replies_params = JSON.parse(params.fetch(:multi_replies_json, "[]")).map do |reply_json| | ||
permitted_params(ActionController::Parameters.new({ reply: reply_json }), [:id]) | ||
end | ||
@multi_replies = @multi_replies_params.map do |reply_params| | ||
Reply.new(reply_params).tap { |r| r.user = current_user } | ||
end | ||
end | ||
|
||
def preview_reply(reply) | ||
# Previewing a specific reply | ||
@post = reply.post | ||
@written = reply | ||
@written.user = current_user unless @written.user | ||
@audits = @written.id.present? ? { @written.id => @written.audits.count } : {} | ||
@reply = @written # So that editor_setup shows the correct characters | ||
preview_replies | ||
end | ||
|
||
def add_to_multi_reply(reply, reply_params) | ||
# Adding a new reply to a multi reply | ||
post_id = params[:reply][:post_id] | ||
ReplyDraft.draft_for(post_id, current_user.id)&.destroy! | ||
|
||
# Save NPC | ||
if reply.character&.new_record? | ||
if reply.character.save | ||
flash[:success] = "Your new NPC has been persisted!" | ||
params[:reply][:character_id] = reply.character.id | ||
reply_params[:character_id] = reply.character.id | ||
reply.character_id = reply.character.id | ||
else | ||
flash[:error] = "There was a problem persisting your new NPC." | ||
end | ||
end | ||
|
||
# Set up editor | ||
@post = reply.post | ||
empty_reply_hash = permitted_params.permit(:character_id, :icon_id, :character_alias_id) | ||
@empty_written = @post.build_new_reply_for(current_user, empty_reply_hash) | ||
@empty_written.editor_mode = reply.editor_mode | ||
@reply = @empty_written # So that editor_setup shows the correct characters | ||
@audits = {} | ||
|
||
# Add reply to list of multi replies | ||
reply.user = current_user unless reply.user | ||
@multi_replies << reply | ||
reply_params[:id] = reply.id if reply.id.present? | ||
@multi_replies_params << reply_params | ||
|
||
preview_replies | ||
end | ||
|
||
def preview_replies | ||
@page_title = @post.subject | ||
|
||
@reply = @written # So that editor_setup shows the correct characters | ||
editor_setup | ||
render :preview | ||
end | ||
|
||
def post_replies(new_reply: nil) | ||
redmvc marked this conversation as resolved.
Show resolved
Hide resolved
redmvc marked this conversation as resolved.
Show resolved
Hide resolved
redmvc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@multi_replies << new_reply if new_reply.present? | ||
|
||
first_reply = @multi_replies.first | ||
begin | ||
Reply.transaction { @multi_replies.each(&:save!) } | ||
rescue ActiveRecord::RecordInvalid => e | ||
errored_reply = @multi_replies.detect { |r| r.errors.present? } || first_reply | ||
render_errors(errored_reply, action: 'created', now: true, err: e) | ||
|
||
redirect_to posts_path and return unless errored_reply.post | ||
redirect_to post_path(errored_reply.post) and return | ||
end | ||
|
||
if @multi_replies.length == 1 | ||
flash[:success] = "Reply posted." | ||
else | ||
flash[:success] = "Replies posted." | ||
end | ||
redirect_to reply_path(first_reply, anchor: "reply-#{first_reply.id}") | ||
end | ||
|
||
def editing_multi_reply? | ||
# If the list of params is present and the first item on the list has the ID stored, I am editing it | ||
@multi_replies_params.present? && (@reply = Reply.find_by_id(@multi_replies_params.first["id"])) | ||
end | ||
|
||
def edit_reply(editing_multi_reply, new_multi_reply: nil) | ||
redmvc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
begin | ||
Reply.transaction do | ||
edit_multi_replies(new_multi_reply) if editing_multi_reply | ||
|
||
@reply.save! | ||
end | ||
rescue ActiveRecord::RecordInvalid => e | ||
if @multi_replies.blank? | ||
render_errors(@reply, action: 'updated', now: true, err: e) | ||
else | ||
errored_reply = @multi_replies.detect { |r| r.errors.present? } || @reply | ||
render_errors(errored_reply, action: 'updated', now: true, err: e) | ||
end | ||
|
||
@audits = { @reply.id => @post.audits.count } | ||
editor_setup | ||
render :edit | ||
else | ||
flash[:success] = "Reply updated." | ||
redirect_to reply_path(@reply, anchor: "reply-#{@reply.id}") | ||
end | ||
end | ||
|
||
def edit_multi_replies(new_multi_reply) | ||
# Add new replies after the one being edited and before the next | ||
if new_multi_reply.present? | ||
# Including the reply in the text editor, not just the ones in the JSON | ||
@multi_replies << new_multi_reply | ||
@multi_replies_params << permitted_params | ||
end | ||
original_reply = @reply.dup | ||
|
||
# Modify the original reply with the parameters of the first reply in the JSON | ||
@reply.assign_attributes(@multi_replies_params.shift) | ||
@multi_replies.shift | ||
|
||
# Check whether there are any further replies beyond the very first one | ||
num_new_replies = @multi_replies_params.length | ||
return if num_new_replies == 0 | ||
|
||
# Reorder the replies after this one | ||
original_reply_order = @reply.order | ||
following_replies = @reply.post.replies.where("reply_order > ?", original_reply_order) | ||
following_replies.update_all(["reply_order = reply_order + ?", num_new_replies]) # rubocop:disable Rails/SkipsModelValidations | ||
|
||
# Create the new replies | ||
@multi_replies_params.each_with_index do |reply_params, idx| | ||
# Create a fake temporary reply with the contents of the original one to be in history | ||
@multi_replies[idx] = new_reply = original_reply.dup | ||
new_reply.order = original_reply_order + idx + 1 | ||
new_reply.save! | ||
|
||
# Update the new reply added with the actual params that should be there | ||
new_reply.update!(reply_params) | ||
end | ||
end | ||
|
||
def make_draft(show_message=true) | ||
if (draft = ReplyDraft.draft_for(params[:reply][:post_id], current_user.id)) | ||
draft.assign_attributes(permitted_params) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid deeply nested control flow statements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My brother in Christ if you have a better suggestion I am all ears