Skip to content

Commit

Permalink
Merge pull request #438 from openjournals/add-editor-to-paper
Browse files Browse the repository at this point in the history
Basic metrics dashboard
  • Loading branch information
arfon committed Aug 19, 2018
2 parents 192a284 + dd0e7da commit 9b9e4ca
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 65 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
source 'https://rubygems.org'

gem 'aasm', '~> 4.1.0'
gem "chartkick"
gem 'bootsnap', require: false
gem 'dotenv', '~> 2.2.1'
gem 'github-markdown', '~> 0.6.9'
gem 'groupdate'
gem 'honeybadger', '~> 3.2.0'
gem 'html-pipeline', '~> 2.7.1'
gem 'commonmarker', '~> 0.17.7'
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
chartkick (3.0.1)
coderay (1.1.2)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
Expand Down Expand Up @@ -83,6 +84,8 @@ GEM
github-markdown (0.6.9)
globalid (0.4.1)
activesupport (>= 4.2.0)
groupdate (4.0.1)
activesupport (>= 4.2)
hashdiff (0.3.7)
hashie (3.5.7)
honeybadger (3.2.0)
Expand Down Expand Up @@ -261,12 +264,14 @@ DEPENDENCIES
aasm (~> 4.1.0)
bootsnap
capybara (~> 2.16.1)
chartkick
coffee-rails (~> 4.2.2)
commonmarker (~> 0.17.7)
custom_error_message (~> 1.1.1)
dotenv (~> 2.2.1)
factory_bot_rails (~> 4.8.2)
github-markdown (~> 0.6.9)
groupdate
honeybadger (~> 3.2.0)
html-pipeline (~> 2.7.1)
jquery-rails (~> 4.3.1)
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require Chart.bundle
//= require chartkick
//= require jquery
//= require jquery_ujs
//= require_tree .
22 changes: 22 additions & 0 deletions app/assets/stylesheets/home.scss
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,28 @@
}
}

table.editor-stats {
width: 910px;
margin: 0px auto;

border-spacing: 5px;

th {
text-align: left;
background: #afafaf;
}

tr.even{
background: #efefef;
}

th, td {
border: 1px solid #3c3c3c;
border-collapse: collapse;
padding: 5px 15px;
}
}

.footer {
padding: 10px 0px;
border-top: 1px solid #ddd;
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ def require_admin_user
end
end

def require_editor
require_user
if current_user && current_user.editor.nil?
flash[:error] = "You are not permitted to view that page"
redirect_to(:root)
false # throw :abort
end
end

def require_complete_profile
if !current_user.profile_complete?
redirect_back(:notice => "Please add an email address to your account before submitting", :fallback_location => root_path)
Expand Down
12 changes: 12 additions & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class HomeController < ApplicationController
before_action :require_user, :only => %w(profile update_profile)
before_action :require_editor, :only => %w(dashboard)

def index
@papers = Paper.visible.limit(10)
Expand All @@ -9,6 +10,17 @@ def about

end

def dashboard
if params[:editor]
@editor = Editor.find_by_login(params[:editor])
else
@editor = Editor.first
end

@accepted_papers = Paper.unscoped.visible.group_by_month(:accepted_at).count
@editor_papers = Paper.unscoped.where(:editor => @editor).visible.group_by_month(:accepted_at).count
end

def update_profile
check_github_username

Expand Down
3 changes: 3 additions & 0 deletions app/models/editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ class Editor < ActiveRecord::Base
validates :last_name, presence: true
validates :login, presence: true

belongs_to :user
has_many :papers

before_save :clear_title, if: :board_removed?
before_save :format_login, if: :login_changed?

Expand Down
34 changes: 29 additions & 5 deletions app/models/paper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class Paper < ActiveRecord::Base
:validate => true,
:foreign_key => "user_id"

belongs_to :editor

include AASM

aasm :column => :state do
Expand All @@ -23,11 +25,11 @@ class Paper < ActiveRecord::Base
end

event :start_meta_review do
transitions :from => :submitted, :to => :review_pending, :after => :create_meta_review_issue
transitions :from => :submitted, :to => :review_pending, :if => :create_meta_review_issue
end

event :start_review do
transitions :from => :review_pending, :to => :under_review, :after => :create_review_issue
transitions :from => :review_pending, :to => :under_review, :if => :create_review_issue
end

event :accept do
Expand All @@ -53,6 +55,8 @@ class Paper < ActiveRecord::Base
default_scope { order(:created_at => :desc) }
scope :recent, lambda { where('created_at > ?', 1.week.ago) }
scope :submitted, lambda { where('state = ?', 'submitted') }

scope :since, -> (date) { where('accepted_at >= ?', date) }
scope :in_progress, -> { where(:state => IN_PROGRESS_STATES) }
scope :visible, -> { where(:state => VISIBLE_STATES) }
scope :everything, lambda { where('state NOT IN (?)', ['rejected', 'withdrawn']) }
Expand Down Expand Up @@ -148,15 +152,32 @@ def review_body(editor, reviewers)
end

# Create a review issue (we know the reviewer and editor at this point)
def create_review_issue(editor, reviewers)
# Return false if the review_issue_id is already set
# Return false if the editor login doesn't match one of the known editors
def create_review_issue(editor_handle, reviewers)
return false if review_issue_id
return false unless editor = Editor.find_by_login(editor_handle)

issue = GITHUB.create_issue(Rails.application.settings["reviews"],
"[REVIEW]: #{self.title}",
review_body(editor, reviewers),
{ :assignee => editor,
review_body(editor_handle, reviewers),
{ :assignee => editor_handle,
:labels => "review" })

set_review_issue(issue.number)
set_editor(editor)
set_reviewers(reviewers)
end

# Update the paper with the reviewer GitHub handles
def set_reviewers(reviewers)
reviewers = reviewers.split(',')
self.update_attribute(:reviewers, reviewers)
end

# Updated the paper with the editor_id
def set_editor(editor)
self.update_attribute(:editor_id, editor.id)
end

# Update the Paper review_issue_id field
Expand Down Expand Up @@ -185,13 +206,16 @@ def create_meta_review_issue(editor_handle)
end

return false if meta_review_issue_id
return false unless editor = Editor.find_by_login(striped_handle)

issue = GITHUB.create_issue(Rails.application.settings["reviews"],
"[PRE REVIEW]: #{self.title}",
meta_review_body(editor_handle),
{ :assignee => striped_handle,
:labels => "pre-review" })

set_meta_review_issue(issue.number)
set_editor(editor)
end

# Update the Paper meta_review_issue_id field
Expand Down
6 changes: 3 additions & 3 deletions app/models/review_issue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ def editor
body.match(/\*\*Editor:\*\*\s*(@\S*|Pending)/i)[1]
end

# Extract the Reviewer from the issue body
def reviewer
body.match(/\*\*Reviewer:\*\*\s*(@\S*|Pending)/i)[1]
# Extract the Reviewers from the issue body
def reviewers
body.match(/Reviewers?:\*\*\s*(.+?)\r?\n/)[1].split(", ") - ["Pending"]
end
end
3 changes: 2 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
class User < ActiveRecord::Base

has_many :papers

has_one :editor

before_create :set_sha

def self.from_omniauth(auth)
Expand Down
46 changes: 46 additions & 0 deletions app/views/home/dashboard.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<div class="wrapper">
<h2>Accepted papers by month</h2>

<%= column_chart [
{ name: "Accepted papers by month", data: @accepted_papers }
], height: "500px", legend: false, library: { scales: { xAxes: [{ position: 'bottom' }], yAxes: [{ position: 'left', gridLines: { display: true, drawBorder: true }, ticks: { min: 0, max: 40, stepSize: 5}}, { position: 'right', gridLines: { display: false, drawBorder: true }, ticks: { min: 0, max: 40, stepSize: 5}}]}} %>

<h2>Accepted papers by month by editor</h2>

<p style="font-weight: bolder; padding-left: 40px;">Select editor: <%= select_tag 'editors', options_from_collection_for_select(Editor.all, "login", "login", params[:editor].blank? ? current_user.editor.login : params[:editor]),
:onchange => "top.location.href='/dashboard?editor=' + this.options[this.selectedIndex].value + '#editor';" %></p>


<%= column_chart [
{ name: "Papers edited by #{@editor.login} by month", data: @editor_papers }
], height: "500px", colors: ["#8FBC8F"], :id => "editor", legend: false, library: { scales: { xAxes: [{ position: 'bottom' }], yAxes: [{ position: 'left', gridLines: { display: true, drawBorder: true }, ticks: { min: 0, max: 20, stepSize: 5}}, { position: 'right', gridLines: { display: false, drawBorder: true }, ticks: { min: 0, max: 20, stepSize: 5}}]}} %>



<h2>Editor statistics</h2>
<table class="editor-stats">
<tr>
<th width="25%">Editor</th><th width="15%">Week</th><th width="15%">Month</th><th width="15%">Quarter</th><th width="15%">Year</th><th width="15%">All time</th>
</tr>
<% Editor.order('LOWER(login)').each do |editor| %>
<tr class="<%= cycle('odd', 'even') -%>">
<td><%= editor.login %></td>
<td><%= editor.papers.visible.since(1.week.ago).count %></td>
<td><%= editor.papers.visible.since(1.month.ago).count %></td>
<td><%= editor.papers.visible.since(3.months.ago).count %></td>
<td><%= editor.papers.visible.since(1.year.ago).count %></td>
<td><%= editor.papers.visible.since(100.year.ago).count %></td>
</tr>
<% end %>
<tr style="font-weight: bolder;">
<td>Totals</td>
<td><%= Paper.visible.since(1.week.ago).count %></td>
<td><%= Paper.visible.since(1.month.ago).count %></td>
<td><%= Paper.visible.since(3.months.ago).count %></td>
<td><%= Paper.visible.since(1.year.ago).count %></td>
<td><%= Paper.visible.since(100.year.ago).count %></td>
</tr>
</table>

<br />
</div>
2 changes: 1 addition & 1 deletion app/views/papers/_list.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<% if paper.pretty_doi == "DOI pending" %>
DOI pending
<% else %>
<%= link_to paper.pretty_doi, paper.doi_with_url, :target => "_blank", :class => "doi" %><span class="octicon octicon-link-external"></span>
<%= link_to paper.pretty_doi, paper.clean_archive_doi, :target => "_blank", :class => "doi" %><span class="octicon octicon-link-external"></span>
<% end %>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
get '/papers/:doi/status.svg', :to => "papers#status", :format => "svg", :constraints => { :doi => /10.21105\/joss\.\d{5}/}
get '/papers/:doi', :to => "papers#show", :constraints => {:doi => /.*/}

get '/dashboard', :to => "home#dashboard"
post '/update_profile', :to => "home#update_profile"
get '/about', :to => 'home#about', :as => 'about'
get '/profile', :to => 'home#profile', :as => 'profile'
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20180816192335_add_editor_id_to_paper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddEditorIdToPaper < ActiveRecord::Migration[5.1]
def change
add_column :editors, :user_id, :integer
add_column :papers, :editor_id, :integer
add_column :papers, :reviewers, :string, array: true, default: []
end
end

0 comments on commit 9b9e4ca

Please sign in to comment.