diff --git a/app/assets/javascripts/report-comment.js b/app/assets/javascripts/report-comment.js new file mode 100644 index 00000000..87195800 --- /dev/null +++ b/app/assets/javascripts/report-comment.js @@ -0,0 +1,9 @@ +/* + * When comment is submitted successfully + * it clears out the text field + */ +$(function() { + $('#new_comment').on('ajax:success', function(a, b,c ) { + $(this).find('#comment_body').val(''); + }); +}); diff --git a/app/assets/stylesheets/backstage.css b/app/assets/stylesheets/backstage.css index 4a97b3f2..35552337 100644 --- a/app/assets/stylesheets/backstage.css +++ b/app/assets/stylesheets/backstage.css @@ -17,7 +17,7 @@ border: solid 5px var(--black-color); -moz-box-sizing: border-box; -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; } #backstage-container .panel-title { @@ -74,7 +74,7 @@ #backstage-container .panel-menu a:focus { cursor: pointer; - background-color: var(--bright-blue-color); + background-color: var(--bright-blue-color); outline: none; } @@ -92,7 +92,7 @@ #backstage-container .panel-filters a.selected { font-weight: 700; - color: var(--light-black-color); + color: var(--light-black-color); } #backstage-container .panel-filters a:hover { @@ -119,12 +119,21 @@ #backstage-container .record-row:hover { cursor: pointer; - background: var(--orange-overlay); + background: var(--orange-overlay); } #backstage-container .record-row:active { cursor: pointer; - background: var(--blue-overlay); + background: var(--blue-overlay); +} + +#backstage-container .record-row .icons-space { + width: 4.5em; +} + +#backstage-container .record-row .icons-space .icon { + font-family: var(--icon-font); + margin-right: 0.3em; } #backstage-container .record-row .row-title { @@ -160,12 +169,12 @@ width: auto; padding: 2em 2em 2em 2em; } - + #backstage-container .control-panel { min-width: 16em; padding: 2em 2em 2em 2em; } - + #backstage-container .panel-descriptor { text-align: left; } diff --git a/app/assets/stylesheets/comments.css b/app/assets/stylesheets/comments.css new file mode 100644 index 00000000..afad32db --- /dev/null +++ b/app/assets/stylesheets/comments.css @@ -0,0 +1,4 @@ +/* + Place all the styles related to the matching controller here. + They will automatically be included in application.css. +*/ diff --git a/app/assets/stylesheets/reports.css b/app/assets/stylesheets/reports.css index 182a1cf4..8d080981 100644 --- a/app/assets/stylesheets/reports.css +++ b/app/assets/stylesheets/reports.css @@ -54,6 +54,71 @@ font-size: 0.9em; } +#backstage-container .comment-row { + padding: 0.3em 1.25em 0.3em 0em; + font-size: 0.9em; + line-height: 1.75em; +} + +#backstage-container .comment-row img.comment-avatar{ + min-width: 24px; + min-height: 24px; + border-radius: 12px; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; +} + +#backstage-container .comment-row .comment-avatar-container { + margin-right: 0.5em; + margin-top: 0.4em; +} + +#backstage-container .comment-row .row-name { + margin-right: 1em; + font-weight: 500; +} + +#backstage-container .comment-row .row-date { + margin-right: 1em; + font-size: 0.8em; + color: var(--gray-color); +} + +#backstage-container .comment-row .row-detail { + line-height: 1.5em; +} + +#backstage-container .comment-field { + margin-top: 0.5em; +} + +#backstage-container .comment-field #comment_body{ + width: 80%; + height: 3em; +} + +#backstage-container .comment-field .send-button, +#backstage-container .comment-field .send-button:hover { + font-family: var(--solid-icon-font); + font-size: 1.8em; + border: none; + color: var(--bright-green-color); + background-color: inherit; + padding: 0.2em; + border-radius: 20%; + margin-left: 0.3em; +} + +#backstage-container .comment-field .send-button:hover { + cursor: pointer; + background-color: var(--dark-white-color); +} + +#backstage-container .button.send-button { + font-family: var(--solid-icon-font); + color: pink; +} + #backstage-container .report-buttons { margin-top: 2em; } @@ -99,7 +164,7 @@ #backstage-container .report-buttons .button:focus { cursor: pointer; - background-color: var(--bright-blue-color); + background-color: var(--bright-blue-color); outline: none; } @@ -118,7 +183,7 @@ margin-left: 0em; margin-top: 2em; } - + #backstage-container .report-buttons a.stealth { margin-left: auto; margin-right: auto; diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb new file mode 100644 index 00000000..c724c51a --- /dev/null +++ b/app/controllers/comments_controller.rb @@ -0,0 +1,20 @@ +class CommentsController < ApplicationController + + def create + @comment = Comment.new(comment_params) + @comment.commenter = current_user + respond_to do |format| + if @comment.save + format.js + else + #TODO if not saved give alert? + end + end + end + + private + + def comment_params + params.require(:comment).permit(:body, :report_id) + end +end diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 396dcacb..14e89406 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -1,13 +1,13 @@ class ReportsController < ApplicationController - + layout "backstage", only: [ :index, :show ] - + before_action :authenticate_user!, only: [ :index, :show, :dismiss, :undismiss ] before_action :ensure_staff, only: [ :index, :show, :dismiss, :undismiss ] before_action :find_report, only: [ :show, :dismiss, :undismiss ] before_action :find_reported_twitch_user, only: [ :show ] around_action :display_timezone - + def index # f is used to filter reports by scope if params[:f].present? && Report::AVAILABLE_SCOPES.key?(params[:f].to_sym) @@ -19,7 +19,7 @@ def index @filter_category = "unresolved" end end - + def show # Create keybot advice message if @reported_twitch_user == nil @@ -29,30 +29,32 @@ def show else @message = "The reported Twitch user did not sign the pledge." end - + + @comment = Comment.new(report: @report) + @comments = @report.comments.includes(:commenter) # TODO: check if reporter has pledged (lookup email/Twitch name) and add info to keybot message # TODO: check if incident stream owner has pledged (Twitch name) and add info to keybot message end - + def new @report = Report.new end def create @report = Report.new(report_params) - + if @report.save # Email notification to staff StaffMailer.notify_staff_new_report(@report).deliver_now - + flash[:notice] = "You've successfully submitted the report. Thank you." redirect_to root_path - else + else flash.now[:alert] ||= "" @report.errors.full_messages.each do |message| flash.now[:alert] << message + ". " - end + end render(action: :new) end end @@ -65,14 +67,14 @@ def dismiss end redirect_to reports_path end - + def undismiss @report.dismissed = false @report.reviewer = nil if @report.save flash[:notice] = "You undismissed the report about #{@report.reported_twitch_name}. It can now be reviewed again." redirect_to report_path(@report) - else + else redirect_to reports_path end end @@ -83,11 +85,11 @@ def find_report rescue ActiveRecord::RecordNotFound redirect_to staff_index_path end - + def find_reported_twitch_user # Check if reported_twitch_name exists on Twitch response = HTTParty.get(URI.escape("#{ENV['TWITCH_API_BASE_URL']}/users?login=#{@report.reported_twitch_name}"), headers: {"Client-ID": ENV['TWITCH_CLIENT_ID'], "Authorization": "Bearer #{TwitchToken.first.valid_token!}"}) - + if response["data"].blank? @reported_twitch_user = nil else @@ -95,20 +97,20 @@ def find_reported_twitch_user end end - private + private def ensure_staff unless current_user.is_moderator? || current_user.is_admin? redirect_to root_url end end - + def display_timezone timezone = Time.find_zone( cookies[:browser_timezone] ) Time.use_zone(timezone) { yield } end - + def report_params params.require(:report).permit(:reporter_email, :reporter_twitch_name, :reported_twitch_name, :incident_stream, :incident_occurred, :incident_description, :recommended_response, :image) end - + end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb new file mode 100644 index 00000000..0ec9ca5f --- /dev/null +++ b/app/helpers/comments_helper.rb @@ -0,0 +1,2 @@ +module CommentsHelper +end diff --git a/app/models/comment.rb b/app/models/comment.rb new file mode 100644 index 00000000..7e02768c --- /dev/null +++ b/app/models/comment.rb @@ -0,0 +1,11 @@ +class Comment < ApplicationRecord + validates_presence_of :report_id, + :commenter_id, + :body + + belongs_to :commenter, class_name: :User, foreign_key: :commenter_id + belongs_to :report + belongs_to :parent_comment, class_name: :Comment, foreign_key: :parent_comment_id, optional: true + has_many :replies, class_name: :Comment, foreign_key: :parent_comment_id + +end diff --git a/app/models/report.rb b/app/models/report.rb index a36a0acb..590f8420 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -1,5 +1,5 @@ class Report < ApplicationRecord - + AVAILABLE_SCOPES = { unresolved: "Unresolved", dismissed: "Dismissed", @@ -7,12 +7,12 @@ class Report < ApplicationRecord revoked: "Revoked", all: "All" }.freeze - + IMAGE_STYLES = { thumb: { resize: "120x120" }, preview: { resize: "240x240" } }.freeze - + validates_presence_of :reported_twitch_name, :incident_stream, :incident_description, @@ -24,22 +24,23 @@ class Report < ApplicationRecord validates :incident_description, length: { maximum: 1000 } - + validates :recommended_response, length: { maximum: 500 } validate :ensure_sane_review belongs_to :reviewer, class_name: :User, foreign_key: :reviewer_id, optional: true - + has_many :comments, class_name: :Comment, foreign_key: :report_id + image_accessor :image - + scope :dismissed, lambda { where("#{table_name}.dismissed IS TRUE") } scope :warned, lambda { where("#{table_name}.warned IS TRUE") } scope :revoked, lambda { where("#{table_name}.revoked IS TRUE") } scope :unresolved, lambda { where("#{table_name}.dismissed IS FALSE AND #{table_name}.warned IS FALSE AND #{table_name}.revoked IS FALSE") } - - + + def image_url(style = :thumb) if style == :original self.image.remote_url @@ -47,7 +48,7 @@ def image_url(style = :thumb) process_image(style).url end end - + protected def ensure_sane_review if (self.dismissed || self.warned || self.revoked) && !(self.dismissed ^ self.warned ^ self.revoked) @@ -62,10 +63,10 @@ def ensure_sane_review end end end - + private - def process_image(style) + def process_image(style) self.image.process(:auto_orient).thumb(Report::IMAGE_STYLES[style][:resize]) end - + end diff --git a/app/views/comments/create.js.erb b/app/views/comments/create.js.erb new file mode 100644 index 00000000..11094d37 --- /dev/null +++ b/app/views/comments/create.js.erb @@ -0,0 +1,6 @@ +/* + * When new comment is created + * it gets added to the view + */ + +$('#comment-view').append("<%= j(render 'reports/comment', comment: @comment) %>"); diff --git a/app/views/reports/_comment.html.erb b/app/views/reports/_comment.html.erb new file mode 100644 index 00000000..288fe531 --- /dev/null +++ b/app/views/reports/_comment.html.erb @@ -0,0 +1,13 @@ +