Skip to content

Commit

Permalink
It's alive! ALIIIIVE!
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtOfCode- committed May 16, 2018
1 parent df43015 commit 02fb753
Show file tree
Hide file tree
Showing 22 changed files with 196 additions and 16 deletions.
3 changes: 3 additions & 0 deletions app/assets/javascripts/review_queues.coffee
@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
3 changes: 3 additions & 0 deletions app/assets/stylesheets/review_queues.scss
@@ -0,0 +1,3 @@
// Place all the styles related to the ReviewQueues controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
47 changes: 47 additions & 0 deletions app/controllers/review_queues_controller.rb
@@ -0,0 +1,47 @@
# frozen_string_literal: true

class ReviewQueuesController < ApplicationController
before_action :set_queue, except: [:index]
before_action :verify_permissions, except: [:index]

def index
@queues = ReviewQueue.all.includes(:items)
end

def queue; end

def next_item
unreviewed = ReviewItem.unreviewed_by(@queue, current_user)
if unreviewed.empty?
render plain: "You've reviewed all available items!"
else
item = unreviewed.first
render "#{item.reviewable_type.underscore.pluralize}/_review_item.html.erb", locals: { queue: @queue, item: item }, layout: nil
end
end

def submit
render json: { status: 'invalid' }, status: 400 unless @queue.responses.map { |r| r[1] }.include? params[:response]
@item = ReviewItem.find params[:item_id]

ReviewResult.create user: current_user, result: params[:response], item: @item

@item.reviewable.custom_review_action(@queue, @item, current_user, params[:response]) if @item.reviewable.respond_to? :custom_review_action
if @item.reviewable.respond_to?(:should_dq?) && @item.reviewable.should_dq?(@queue)
@item.update(completed: true)
end

render json: { status: 'ok' }
end

private

def set_queue
@queue = ReviewQueue[params[:name]]
end

def verify_permissions
return if user_signed_in? && current_user.has_role?(@queue.privileges)
not_found
end
end
4 changes: 4 additions & 0 deletions app/helpers/review_queues_helper.rb
@@ -0,0 +1,4 @@
# frozen_string_literal: true

module ReviewQueuesHelper
end
19 changes: 19 additions & 0 deletions app/javascript/review.js
@@ -1,3 +1,5 @@
import { route } from './util';

$(() => {
$(document).on('ajax:success', 'a.feedback-button[data-remote]', e => {
if (!$(e.target).hasClass('on-post')) {
Expand All @@ -6,3 +8,20 @@ $(() => {
}
});
});

route(/\/review\/\w+/i, async () => {
const loadNextPost = async () => {
const response = await fetch(location.pathname + '/next', {
credentials: 'include'
});
const html = await response.text();
$('.review-item-container').html(html);
};

loadNextPost();

$(document).on('ajax:success', '.review-submit-link', () => {
$('.review-item-container').text('Loading...');
loadNextPost();
});
});
1 change: 0 additions & 1 deletion app/models/feedback.rb
Expand Up @@ -13,7 +13,6 @@ class Feedback < ApplicationRecord
belongs_to :user
belongs_to :invalidated_by, class_name: 'User', foreign_key: 'invalidated_by'
belongs_to :api_key
has_one :review, class_name: 'ReviewResult', required: false, dependent: :destroy

before_save :check_for_user_assoc
before_save :check_for_dupe_feedback
Expand Down
23 changes: 22 additions & 1 deletion app/models/post.rb
Expand Up @@ -18,7 +18,7 @@ class Post < ApplicationRecord
has_many :flag_logs, dependent: :destroy
has_many :flags, dependent: :destroy
has_and_belongs_to_many :spam_domains
has_many :reviews, class_name: 'ReviewResult', dependent: :destroy
has_one :review_item, as: :reviewable
has_many :comments, class_name: 'PostComment', dependent: :destroy

scope(:includes_for_post_row, -> do
Expand All @@ -39,6 +39,14 @@ class Post < ApplicationRecord

scope(:undeleted, -> { where(deleted_at: nil) })

after_commit do
if review_item.present? && should_dq?(ReviewQueue['posts'])
review_item.update(completed: true)
elsif !review_item.present?
ReviewItem.create(reviewable: self, queue: ReviewQueue['posts'], completed: false)
end
end

after_commit :parse_domains, on: :create

after_create do
Expand Down Expand Up @@ -319,4 +327,17 @@ def parse_domains
domain.posts << self unless domain.posts.include? self
end
end

def custom_review_action(_queue, _item, user, response)
feedbacks.create(user: user, feedback_type: response)
end

def should_dq?(queue)
case queue.name
when 'posts'
feedbacks.count >= 2
else
false
end
end
end
12 changes: 11 additions & 1 deletion app/models/review_item.rb
Expand Up @@ -2,7 +2,17 @@

class ReviewItem < ApplicationRecord
belongs_to :user
belongs_to :review_queue
belongs_to :queue, class_name: 'ReviewQueue', foreign_key: 'review_queue_id'
belongs_to :reviewable, polymorphic: true
has_many :results, class_name: 'ReviewResult'

validates :reviewable_type, inclusion: { in: ['Post'] }

scope(:active, -> { where(completed: false) })
scope(:completed, -> { where(completed: true) })

def self.unreviewed_by(queue, user)
joins("LEFT JOIN review_results rr ON rr.review_item_id = review_items.id AND rr.user_id = #{user.id}").where(review_items: { queue: queue },
rr: { id: nil })
end
end
7 changes: 7 additions & 0 deletions app/models/review_queue.rb
Expand Up @@ -4,7 +4,14 @@ class ReviewQueue < ApplicationRecord
has_many :items, class_name: 'ReviewItem'
has_many :results, class_name: 'ReviewResult', through: :items

serialize :responses, JSON

def self.[](key)
find_by name: key
end

def should_dq?(item)
item.reviewable.should_dq?(self) if item.reviewable.respond_to? :should_dq?
false
end
end
4 changes: 2 additions & 2 deletions app/views/layouts/application.html.erb
Expand Up @@ -49,8 +49,8 @@
<%= nav_link GraphsController %>
<%= nav_link SearchController %>
<% if user_signed_in? %>
<%= nav_link ReviewController do %>
<% review_items = Post.unreviewed.count %>
<%= nav_link ReviewQueuesController, label: 'review' do %>
<% review_items = ReviewItem.active.count %>
<%# badge hides itself if it doesn’t have contents. %>
<span class="reviews-count badge"><% unless review_items == 0 || !current_user.has_role?(:reviewer) %><%= review_items %><% end %></span>
<% end %>
Expand Down
4 changes: 4 additions & 0 deletions app/views/posts/_review_item.html.erb
@@ -0,0 +1,4 @@
<div class="review-item">
<%= render 'review_queues/responses', queue: queue, item: item %>
<%= render 'posts/post', post: item.reviewable, expand_post: true %>
</div>
8 changes: 8 additions & 0 deletions app/views/review_queues/_responses.html.erb
@@ -0,0 +1,8 @@
<div class="panel panel-default">
<div class="panel-body">
<% @queue.responses.each do |r| %>
<%= link_to r[0], submit_review_path(name: queue.name, item_id: item.id, response: r[1]), class: 'btn btn-primary review-submit-link',
method: :post, remote: true %>
<% end %>
</div>
</div>
13 changes: 13 additions & 0 deletions app/views/review_queues/index.html.erb
@@ -0,0 +1,13 @@
<h1>Review Queues</h1>

<% @queues.each do |q| %>
<div class="panel panel-default">
<div class="panel-body">
<h4>
<%= link_to q.name.titleize, review_queue_path(q.name) %>
<span class="badge"><%= q.items.active.count if q.items.active.count > 0 %></span>
</h4>
<p><%= q.description %></p>
</div>
</div>
<% end %>
6 changes: 6 additions & 0 deletions app/views/review_queues/queue.html.erb
@@ -0,0 +1,6 @@
<h1>Review <%= @queue.name.titleize %></h1>
<p><%= @queue.description %></p>

<div class="review-item-container">
Loading...
</div>
15 changes: 7 additions & 8 deletions config/routes.rb
Expand Up @@ -43,14 +43,6 @@
post ':id/update_mod_sites', to: 'users#update_mod_sites', as: :update_mod_sites
end

scope '/review' do
root to: 'review#index', as: :review
post 'feedback', to: 'review#add_feedback', as: :review_feedback
post 'skip', to: 'review#skip', as: :review_skip
get 'history', to: 'review#history', as: :review_history
post 'unskip', to: 'review#delete_skip', as: :review_unskip
end

get 'spammers', to: 'stack_exchange_users#index'
get 'spammers/sites', to: 'stack_exchange_users#sites', as: :spammers_site_index
get 'spammers/site', to: 'stack_exchange_users#on_site', as: :spammers_on_site
Expand Down Expand Up @@ -375,6 +367,13 @@
get 'processing', to: 'dashboard#data_processing', as: :data_processing
end

scope 'review' do
root to: 'review_queues#index', as: :review_queues
get ':name', to: 'review_queues#queue', as: :review_queue
get ':name/next', to: 'review_queues#next_item', as: :next_review_item
post ':name/:item_id', to: 'review_queues#submit', as: :submit_review
end

# This should always be right at the end of this file, so that it doesn't override other routes.
mount API::Base => '/api'
end
1 change: 0 additions & 1 deletion db/migrate/20180515234548_create_review_queues.rb
Expand Up @@ -6,7 +6,6 @@ def change
t.string :name
t.string :privileges
t.text :responses
t.integer :reviews_per_item

t.timestamps
end
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20180516122833_setup_posts_review_queue.rb
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class SetupPostsReviewQueue < ActiveRecord::Migration[5.2]
def change
ReviewQueue.create name: 'posts', privileges: 'reviewer', responses: [['True Positive', 'tp'], ['False Positive', 'fp'], %w[NAA naa]]
end
end
7 changes: 7 additions & 0 deletions db/migrate/20180516123826_add_completed_to_review_items.rb
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddCompletedToReviewItems < ActiveRecord::Migration[5.2]
def change
add_column :review_items, :completed, :boolean
end
end
7 changes: 7 additions & 0 deletions db/migrate/20180516201704_add_description_to_review_queues.rb
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddDescriptionToReviewQueues < ActiveRecord::Migration[5.2]
def change
add_column :review_queues, :description, :text
end
end
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddDescriptionToPostsReviewQueue < ActiveRecord::Migration[5.2]
def change
ReviewQueue['posts'].update(description: 'Review new reports as they come in and add feedback to them.')
end
end
5 changes: 3 additions & 2 deletions db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2018_05_15_234932) do
ActiveRecord::Schema.define(version: 2018_05_16_201733) do

create_table "abuse_comments", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
t.bigint "user_id"
Expand Down Expand Up @@ -374,6 +374,7 @@
t.bigint "reviewable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "completed"
t.index ["review_queue_id"], name: "index_review_items_on_review_queue_id"
t.index ["reviewable_type", "reviewable_id"], name: "index_review_items_on_reviewable_type_and_reviewable_id"
end
Expand All @@ -382,9 +383,9 @@
t.string "name"
t.string "privileges"
t.text "responses"
t.integer "reviews_per_item"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "description"
end

create_table "review_results", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
Expand Down
9 changes: 9 additions & 0 deletions test/controllers/review_queues_controller_test.rb
@@ -0,0 +1,9 @@
# frozen_string_literal: true

require 'test_helper'

class ReviewQueuesControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end

0 comments on commit 02fb753

Please sign in to comment.