From 9b50ec652cd8f80a16bd82987bd9f8eba389a2eb Mon Sep 17 00:00:00 2001 From: MrYummy Date: Thu, 15 Jun 2017 14:27:42 +0200 Subject: Made messages more thread-like (replies, editing, etc.) --- app/controllers/messagereplies_controller.rb | 77 ++++++++++++++++++++++ app/controllers/messages_controller.rb | 50 ++++++++++++-- app/models/message.rb | 34 ++++++++++ app/models/messagereply.rb | 67 +++++++++++++++++++ app/models/user.rb | 2 + app/views/forumthreads/show.html.erb | 2 +- app/views/messagereplies/_new.html.erb | 5 ++ app/views/messagereplies/_reply.html.erb | 17 +++++ app/views/messagereplies/edit.html.erb | 15 +++++ app/views/messages/edit.html.erb | 17 +++++ app/views/messages/index.html.erb | 34 ++++++++-- app/views/messages/show.html.erb | 33 ++++++++++ app/views/threadreplies/_new.html.erb | 2 +- app/views/threadreplies/edit.html.erb | 2 +- app/views/users/show.html.erb | 4 +- config/routes.rb | 1 + db/migrate/20170524181458_create_messages.rb | 3 +- db/migrate/20170613021450_create_messagereplies.rb | 13 ++++ .../20170613144233_add_user_editor_to_messages.rb | 5 ++ db/schema.rb | 15 ++++- db/seeds.rb | 3 +- 21 files changed, 380 insertions(+), 21 deletions(-) create mode 100644 app/controllers/messagereplies_controller.rb create mode 100644 app/models/messagereply.rb create mode 100644 app/views/messagereplies/_new.html.erb create mode 100644 app/views/messagereplies/_reply.html.erb create mode 100644 app/views/messagereplies/edit.html.erb create mode 100644 app/views/messages/edit.html.erb create mode 100644 db/migrate/20170613021450_create_messagereplies.rb create mode 100644 db/migrate/20170613144233_add_user_editor_to_messages.rb diff --git a/app/controllers/messagereplies_controller.rb b/app/controllers/messagereplies_controller.rb new file mode 100644 index 0000000..e01501b --- /dev/null +++ b/app/controllers/messagereplies_controller.rb @@ -0,0 +1,77 @@ +class MessagerepliesController < ApplicationController + + def edit + @reply = Messagereply.find(params[:id]) + if mod? || @reply.author.is?(current_user) + else + flash[:alert] = "You are not allowed to edit this reply" + redirect_to @reply.message + end + end + + def create + message = Message.find(params[:message_id]) + if [message.user_sender, message.user_target].include? current_user + @reply = Messagereply.new(reply_params) + @reply.user_author = current_user + @reply.message = message + if @reply.save + @reply.message.update_attributes(user_hidden: nil) + if false + @reply.send_new_message_reply_mail + end + position = message.replies.count - 1 + page = position / Kaminari.config.default_per_page + 1 + redirect_to message_path(@reply.message, page: page) + "#reply-#{@reply.id}", notice: 'Reply created!' + else + flash[:alert] = "Could not create reply." + redirect_to Message.find(params[:message_id]) + end + else + flash[:alert] = "You are not allowed to create replies." + redirect_to Message.find(params[:message_id]) + end + end + + def update + @reply = Messagereply.find(params[:id]) + if mod? || @reply.author.is?(current_user) + old_content = @reply.text_was + if @reply.update_attributes(reply_params) + if false + @reply.send_new_reply_mail(old_content) + end + flash[:notice] = "Reply updated!" + position = @reply.message.replies.index(@reply) + page = position / Kaminari.config.default_per_page + 1 + redirect_to message_path(@reply.message, page: page) + "#reply-#{@reply.id}" + else + flash[:alert] = "There was a problem while updating your reply" + render action: "edit" + end + else + flash[:alert] = "You are not allowed to edit this reply" + redirect_to @reply.message + end + end + + def destroy + @reply = Messagereply.find(params[:id]) + if mod? || @reply.author.is?(current_user) + if @reply.destroy + flash[:notice] = "Reply deleted!" + else + flash[:alert] = "There was a problem while deleting this reply" + end + else + flash[:alert] = "You are not allowed to delete this reply" + end + redirect_to @reply.message + end + + private + + def reply_params + params.require(:messagereply).permit(:text) + end +end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 480a671..8f618d3 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,16 +1,32 @@ class MessagesController < ApplicationController - before_filter :check_permission, only: :destroy + before_filter :set_current + def set_current + User.current = current_user + end + + before_filter :check_permission, only: [:show, :edit, :update, :destroy] def index if current_user - @messages = Message.where(user_target: current_user).page(params[:page]) + @messages = Message.where("(user_sender_id = ? OR user_target_id = ?) AND (user_hidden_id != ? OR user_hidden_id IS NULL)", current_user.id, current_user.id, current_user.id).page(params[:page]) else flash[:alert] = "Please log in to see your private messages." redirect_to blogposts_path end end + def show + @replies = @message.replies.page(params[:page]) + end + + def edit + unless mod? || @message.author.is?(current_user) + flash[:alert] = "You are not allowed to edit this message!" + redirect_to @message + end + end + def new if current_user @message = Message.new @@ -47,12 +63,32 @@ class MessagesController < ApplicationController end end + def update + if mod? || @message.user_sender.is?(current_user) + @message.user_editor_id = current_user.id + @message.attributes = message_params + if @message.save + redirect_to @message, notice: 'Message has been updated.' + else + flash[:alert] = "There was a problem while updating the message." + render action: "edit" + end + else + flash[:alert] = "You are not allowed to edit this message!" + redirect_to @message + end + end + def destroy - if @message.user_target.is?(current_user) + if [@message.user_target, @message.user_sender].include?(current_user) if @message.destroy flash[:notice] = "Message deleted!" else - flash[:alert] = "There was a problem while deleting this message." + unless @message.user_hidden + flash[:alert] = "There was a problem while deleting this message." + else + Message.find(@message.id).update_attributes(user_hidden: current_user) + end end else flash[:alert] = "You are not allowed to delete this message." @@ -73,15 +109,15 @@ class MessagesController < ApplicationController def message_params(add = []) params[:message][:user_target_id] = User.find_by(ign: params[:message][:user_target].strip).try(:id) params[:message][:user_sender_id] = User.find_by(ign: params[:message][:user_sender]).id - - params.require(:message).permit([:subject, :text, :user_target_id, :user_sender_id]) + params[:message][:user_hidden_id] = User.find_by(ign: params[:message][:user_hidden]).try(:id) +params.require(:message).permit([:subject, :text, :user_target_id, :user_sender_id]) end private def check_permission @message = Message.find(params[:id]) - unless @message.user_target == current_user + unless [@message.user_target, @message.user_sender].include? current_user flash[:alert] = "You are not allowed to view this message" redirect_to home_statics_path end diff --git a/app/models/message.rb b/app/models/message.rb index 3c5ad58..35c47ef 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -4,12 +4,34 @@ class Message < ActiveRecord::Base belongs_to :user_sender, class_name: "User", foreign_key: "user_sender_id" belongs_to :user_target, class_name: "User", foreign_key: "user_target_id" + belongs_to :user_editor, class_name: "User", foreign_key: "user_editor_id" + belongs_to :user_hidden, class_name: "User", foreign_key: "user_hidden_id" + validates_presence_of :user_sender, :user_target, :text, :subject validates_length_of :text, in: 1..8000 validates_length_of :subject, in: 1..2000 + has_many :messagereplies + + accepts_nested_attributes_for :messagereplies + + before_destroy :do_destroy? + + def do_destroy? + unless user_hidden || user_sender == user_target + update_attributes(user_hidden: User.current) + return false + else + return true + end + end + + def to_s + subject + end + def sender @sender ||= if self.user_sender.present? user_sender @@ -26,6 +48,18 @@ class Message < ActiveRecord::Base end end + def editor + @editor ||= (self.user_editor || User.first) + end + + def edited? + !!user_editor_id + end + + def replies + messagereplies + end + def send_new_message_mail begin mail = RedstonerMailer.new_message_mail(user_target, self) diff --git a/app/models/messagereply.rb b/app/models/messagereply.rb new file mode 100644 index 0000000..390ed12 --- /dev/null +++ b/app/models/messagereply.rb @@ -0,0 +1,67 @@ +class Messagereply < ActiveRecord::Base + + include MailerHelper + include UsersHelper + + belongs_to :message + belongs_to :user_author, class_name: "User", foreign_key: "user_author_id" + belongs_to :user_editor, class_name: "User", foreign_key: "user_editor_id" + + + + validates_presence_of :text + validates_length_of :text, in: 1..8000 + + def get_message + message + end + + def author + @author ||= if self.user_author.present? + user_author + else + User.first + end + end + + def editor + # can be nil + @editor ||= user_editor + end + + def edited? + !!user_editor_id + end + + def send_new_reply_mail(old_content = "") + users = mentions(content) - mentions(old_content) + + # thread + replies + posts = message.replies.to_a + posts << message if message.author.mail_own_message_reply? + # only send "reply" mail when reply is new + unless old_content.present? + posts.each do |post| + # don't send mail to the author of this reply, don't send to banned/disabled users + if post.author != author && post.author.normal? && post.author.confirmed? # && + users << post.author if post.author.mail_other_thread_reply? + end + end + end + # making sure we don't send multiple mails to the same user + users.uniq! + + mails = [] + users.each do |usr| + begin + mails << RedstonerMailer.new_thread_reply_mail(usr, self) + rescue => e + Rails.logger.error "---" + Rails.logger.error "WARNING: Failed to create new_thread_reply_mail (view) for reply#: #{@self.id}, user: #{@user.name}, #{@user.email}" + Rails.logger.error e.message + Rails.logger.error "---" + end + end + background_mailer(mails) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 9ddd4f0..4d06f80 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -24,6 +24,8 @@ class User < ActiveRecord::Base has_many :blogposts has_many :comments + cattr_accessor :current + # foo.bar.is?(current_user) def is? (user) self == user diff --git a/app/views/forumthreads/show.html.erb b/app/views/forumthreads/show.html.erb index 876d55d..ffec8c7 100644 --- a/app/views/forumthreads/show.html.erb +++ b/app/views/forumthreads/show.html.erb @@ -44,4 +44,4 @@ <% else %>

Please <%= link_to "Log in", login_path(return_path: request.env['PATH_INFO']), action: "new" %> to post a reply.

<% end %> - \ No newline at end of file + diff --git a/app/views/messagereplies/_new.html.erb b/app/views/messagereplies/_new.html.erb new file mode 100644 index 0000000..a7b7780 --- /dev/null +++ b/app/views/messagereplies/_new.html.erb @@ -0,0 +1,5 @@ +<%= form_for [reply.get_message, reply] do |f| %> + <%= render partial: "md_editor", locals: {name: "messagereply[text]", content: reply.text} %> +

<%= f.submit "Reply", class: "btn blue" %>

+<% end %> + diff --git a/app/views/messagereplies/_reply.html.erb b/app/views/messagereplies/_reply.html.erb new file mode 100644 index 0000000..c17121a --- /dev/null +++ b/app/views/messagereplies/_reply.html.erb @@ -0,0 +1,17 @@ +
+
+ <%= link_to(reply.author.avatar(64), reply.author, title: reply.author.ign) %> + <%= render partial: "users/username", locals: { user: reply.author } %> + <%= link_to "#reply-#{reply.id}" do %> + <%= ago reply.created_at %> + <% end %> + + <%= link_to "edit", edit_message_messagereply_path(reply.message, reply), class: "editlink" if mod? || reply.author.is?(current_user) %> +
+
+
+
+ <%= render_md(reply.text).html_safe %> +
+
+
diff --git a/app/views/messagereplies/edit.html.erb b/app/views/messagereplies/edit.html.erb new file mode 100644 index 0000000..978acd5 --- /dev/null +++ b/app/views/messagereplies/edit.html.erb @@ -0,0 +1,15 @@ +<% title "Edit Message Reply: #{@reply.message.subject}" %> + +<% + position = @reply.message.replies.index(@reply) + page = position / Kaminari.config.default_per_page + 1 +%> + +<%= link_to "Messages", messages_path %> → <%= link_to @reply.message, message_path(@reply.message, page: page) + "#reply-#{@reply.id}" %> → Edit reply +

Edit reply

+<%= form_for [@reply.message, @reply] do |f| %> + <%= render partial: "md_editor", locals: {name: "messagereply[text]", content: @reply.text} %> +

<%= f.submit "Reply", class: "btn blue left" %>

+<% end %> +

<%= button_to "Delete reply", [@reply.message, @reply], method: "delete", data: {confirm: "Delete reply forever?"}, class: "btn red right" %>

+
diff --git a/app/views/messages/edit.html.erb b/app/views/messages/edit.html.erb new file mode 100644 index 0000000..c1ad1ed --- /dev/null +++ b/app/views/messages/edit.html.erb @@ -0,0 +1,17 @@ +<% title "Edit Thread: #{@message}" %> + +

Edit thread

+<%= link_to "Messages", messages_path %> → <%= link_to @message, @message %> → Edit Message +<%= form_for @message do |f|%> +
+ <%= f.text_field :subject, placeholder: "Subject" %> +
+
+ <%= render partial: "md_editor", locals: {name: "message[text]", content: @message.text} %> +

<%= f.submit "Update message", class: "btn blue left" %>

+ <%= f.hidden_field :user_sender, value: @message.user_sender %> + <%= f.hidden_field :user_target, value: @message.user_target %> +<% end %> +<%= button_to "Delete ", @message, :method => "delete", data: {confirm: "Delete message & comments forever?"}, class: "btn red right" %> +
+ diff --git a/app/views/messages/index.html.erb b/app/views/messages/index.html.erb index 036243d..de78f9b 100644 --- a/app/views/messages/index.html.erb +++ b/app/views/messages/index.html.erb @@ -15,13 +15,21 @@ <% @messages.each do |message| %>
- <%= link_to(message.user_sender.avatar(64), message.user_sender, title: message.user_sender.ign) %> - <%= render partial: "users/username", locals: { user: message.user_sender } %> - <%= ago message.created_at %> - + <% + if current_user == message.user_sender + user = message.user_target + else + user = message.user_sender + end + %> + <%= link_to(user.avatar(64), user, title: user.ign) %> + <%= render partial: "users/username", locals: { user: user } %> + +   + <%= link_to message.subject, message %>   |   - <%= link_to message.subject, messages_path %> + <%= ago message.created_at %>
<%= link_to "Delete message", message, :method => "delete", class: "editlink", data: {confirm: "Delete this message forever?"} %>
@@ -29,7 +37,21 @@
- <%= render_md(truncate message.text, length: 20, omission: "...").html_safe %> + <%= truncate message.text, length: 20, omission: "..." %> +
+ <% if rpl = message.replies.last %> + <%= rpl.author.name %> + <% + position = message.replies.count - 1 + page = position / Kaminari.config.default_per_page + 1 + %> + <%= link_to "replied", message_path(message, page: page) + "#reply-#{rpl.id}" %> + <%= ago rpl.created_at %>. + <% else %> + No replies yet. + <% end %> +
+
diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb index e69de29..6413d30 100644 --- a/app/views/messages/show.html.erb +++ b/app/views/messages/show.html.erb @@ -0,0 +1,33 @@ +<%= link_to "Messages", messages_path %> +

<%= title @message.subject %>

+
+
+ <%= link_to(@message.sender.avatar(64), @message.sender, title: @message.sender.ign) %> + <%= render partial: "users/username", locals: { user: @message.sender } %> + <%= link_to p do %> + <%= ago @message.created_at %> + <% end %> + <%= link_to "edit", edit_message_path(@message), class: "editlink" if mod? || @message.sender.is?(current_user) %> +
+
+
+ <% if @message.edited? %> +
+ Last edited <%= ago @message.updated_at %> by <%= link_to @message.editor.name, @message.editor %>. +
+ <% end %> +
+ <%= render_md(@message.text).html_safe %> +
+
+
+
+

<%= "#{pluralize(@message.replies.size, 'reply')}." %>

+ <% @replies.each do |reply| %> + <%= render partial: "messagereplies/reply", locals: {reply: reply} %> + <% end %> + + <%= paginate @replies %> + + <%= render partial: "messagereplies/new", locals: {reply: Messagereply.new(message: @message)} %> +
diff --git a/app/views/threadreplies/_new.html.erb b/app/views/threadreplies/_new.html.erb index b0c4b5e..bdf9df8 100644 --- a/app/views/threadreplies/_new.html.erb +++ b/app/views/threadreplies/_new.html.erb @@ -1,4 +1,4 @@ <%= form_for [reply.thread, reply] do |f| %> <%= render partial: "md_editor", locals: {name: "threadreply[content]", content: reply.content} %>

<%= f.submit "Reply#{ ' (Locked)' if reply.thread.locked? }", class: "btn blue" %>

-<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/threadreplies/edit.html.erb b/app/views/threadreplies/edit.html.erb index c009cb0..d14966a 100644 --- a/app/views/threadreplies/edit.html.erb +++ b/app/views/threadreplies/edit.html.erb @@ -12,4 +12,4 @@

<%= f.submit "Reply", class: "btn blue left" %>

<% end %>

<%= button_to "Delete reply", [@reply.thread, @reply], method: "delete", data: {confirm: "Delete reply forever?"}, class: "btn red right" %>

-
\ No newline at end of file +
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index d9eb123..a48eae2 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -11,8 +11,8 @@ <%= link_to "edit profile", edit_user_path(@user), :class => "btn blue" %> <% end %> <% if @user.is?(current_user) %> - <%= link_to "Private Messages (#{Message.where(user_target: current_user).count})", messages_path, :class => "btn blue" %> - <% else %> + <%= link_to "Private Messages (#{Message.where("user_sender_id = ? OR user_target_id = ?", current_user.id, current_user.id).count})", messages_path, :class => "btn blue" %> + <% elsif current_user %> <%= link_to "Send this user a message", new_message_path(user_target: @user.ign), :class => "btn blue" %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 309b96a..12330d4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,6 +42,7 @@ Redstoner::Application.routes.draw do end resources :messages do + resources :messagereplies, path: 'replies' collection do post 'destroy_all' end diff --git a/db/migrate/20170524181458_create_messages.rb b/db/migrate/20170524181458_create_messages.rb index a07fd9d..b253742 100644 --- a/db/migrate/20170524181458_create_messages.rb +++ b/db/migrate/20170524181458_create_messages.rb @@ -1,10 +1,11 @@ class CreateMessages < ActiveRecord::Migration def change create_table :messages do |t| - t.text :message t.references :user_sender t.references :user_target + t.references :user_editor + t.references :user_hidden t.datetime :created_at end end diff --git a/db/migrate/20170613021450_create_messagereplies.rb b/db/migrate/20170613021450_create_messagereplies.rb new file mode 100644 index 0000000..21ef3bc --- /dev/null +++ b/db/migrate/20170613021450_create_messagereplies.rb @@ -0,0 +1,13 @@ +class CreateMessagereplies < ActiveRecord::Migration + def change + create_table :messagereplies do |t| + t.text :text + + t.references :user_author + t.references :user_editor + t.references :message + + t.timestamps null: true + end + end +end diff --git a/db/migrate/20170613144233_add_user_editor_to_messages.rb b/db/migrate/20170613144233_add_user_editor_to_messages.rb new file mode 100644 index 0000000..cc4c7f7 --- /dev/null +++ b/db/migrate/20170613144233_add_user_editor_to_messages.rb @@ -0,0 +1,5 @@ +class AddUserEditorToMessages < ActiveRecord::Migration + def change + add_reference :messages, :user_editor + end +end diff --git a/db/schema.rb b/db/schema.rb index 9c631a8..269d20e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170525184355) do +ActiveRecord::Schema.define(version: 20170613144233) do create_table "blogposts", force: :cascade do |t| t.string "title", limit: 191 @@ -76,11 +76,24 @@ ActiveRecord::Schema.define(version: 20170525184355) do t.string "color", limit: 191 end + create_table "messagereplies", force: :cascade do |t| + t.text "text", limit: 65535 + t.integer "user_author_id", limit: 4 + t.integer "user_editor_id", limit: 4 + t.integer "message_id", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "messages", force: :cascade do |t| t.text "text", limit: 65535 t.integer "user_sender_id", limit: 4 t.integer "user_target_id", limit: 4 + t.integer "user_hidden_id", limit: 4 t.datetime "created_at" + t.datetime "updated_at" + t.string "subject", limit: 191 + t.integer "user_editor_id", limit: 4 end create_table "register_tokens", force: :cascade do |t| diff --git a/db/seeds.rb b/db/seeds.rb index 78097d8..6c4946d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -61,5 +61,6 @@ Message.create!( user_sender_id: 2, user_target_id: 2, text: "This is a very long message that I will be using to test a plentitude of things. :)", - created_at: Time.utc(0).to_datetime + created_at: Time.utc(0).to_datetime, + subject: "Hello there!" ) -- cgit v1.2.3