diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb
new file mode 100644
index 0000000..9cf7e4e
--- /dev/null
+++ b/app/controllers/report_controller.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ReportController < ApplicationController
+ def index; end
+
+ def algorithm_metrics
+ @metrics = if params[:type] == 'aggregate'
+ Metrics::Algorithms.aggregates
+ else
+ Metrics::Algorithms.monthlies
+ end
+ end
+end
diff --git a/app/helpers/metrics_helper.rb b/app/helpers/metrics_helper.rb
new file mode 100644
index 0000000..adbe747
--- /dev/null
+++ b/app/helpers/metrics_helper.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module MetricsHelper
+ # Calculate percentage of search events in which we had any Detection match
+ def percent_match(metric)
+ (sum_matched(metric) / sum_total(metric) * 100).round(2)
+ end
+
+ # Sums all detection matches for a given Metrics::Algorithms record
+ def sum_matched(metric)
+ metric.doi.to_f + metric.issn.to_f + metric.isbn.to_f + metric.pmid.to_f + metric.journal_exact.to_f + metric.suggested_resource_exact.to_f
+ end
+
+ # Calculates total events for a given Metrics::Algorithms record
+ def sum_total(metric)
+ sum_matched(metric) + metric.unmatched.to_f
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 4c4f547..6687700 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -7,12 +7,18 @@ class Ability
# See the wiki for details:
# https://github.com/CanCanCommunity/cancancan/blob/develop/docs/define_check_abilities.md
def initialize(user)
+ # Actions allowed for non-authenticated Users should add `skip_before_action :require_user`
+
+ # Start of Rules for all authenticated user with no additional roles required
return if user.blank?
- # Rules will go here.
- # all authenticated
- # can :view, :playground
+ can :manage, :detector__suggested_resource
+ can :manage, Detector::SuggestedResource
+
+ can :view, :report
+ # End of Rules for all authenticated user with no additional roles required
+ # Rules for admins
return unless user.admin?
can :manage, :all
diff --git a/app/models/metrics/algorithms.rb b/app/models/metrics/algorithms.rb
index 82b7fd7..3368641 100644
--- a/app/models/metrics/algorithms.rb
+++ b/app/models/metrics/algorithms.rb
@@ -21,6 +21,9 @@ module Metrics
class Algorithms < ApplicationRecord
self.table_name = 'metrics_algorithms'
+ scope :monthlies, -> { where.not(month: nil).order(month: :asc) }
+ scope :aggregates, -> { where(month: nil).order(month: :asc) }
+
# generate metrics data about SearchEvents matches
#
# @note This is expected to only be run once per month per type of aggregation (once with no month supplied, once
diff --git a/app/views/admin/application/_navigation.html.erb b/app/views/admin/application/_navigation.html.erb
new file mode 100644
index 0000000..abfe4cc
--- /dev/null
+++ b/app/views/admin/application/_navigation.html.erb
@@ -0,0 +1,27 @@
+<%#
+# Navigation
+
+This partial is used to display the navigation in Administrate.
+By default, the navigation contains navigation links
+for all resources in the admin dashboard,
+as defined by the routes in the `admin/` namespace
+
+This local template was forked from the administrate version to allow direct usage of
+the `can?` check rather than administrates `accessible_action?` which didn't work in
+our environment. Our option was to fork this template or monkey patch that method. This
+felt least likely to have undesired side effects as `accessible_action?` is used in more
+places than just this and we haven't noted it not working as expected there. If we realize
+other templates are also having it not work as needed, we should monkey patch that method
+and delete this template.
+%>
+
+
diff --git a/app/views/layouts/_site_nav.html.erb b/app/views/layouts/_site_nav.html.erb
index 7f1be8a..f5f798f 100644
--- a/app/views/layouts/_site_nav.html.erb
+++ b/app/views/layouts/_site_nav.html.erb
@@ -16,6 +16,12 @@
<% if can? :view, :playground %>
<%= link_to('Playground', '/playground', class: 'nav-item') %>
<% end %>
+ <% if can? :manage, :detector__suggested_resource %>
+ <%= link_to('Suggested Resources', admin_detector_suggested_resources_path, class: 'nav-item') %>
+ <% end %>
+ <% if can? :view, :report %>
+ <%= link_to('Reports', report_path, class: 'nav-item') %>
+ <% end %>
<% end %>
diff --git a/app/views/report/algorithm_metrics.html.erb b/app/views/report/algorithm_metrics.html.erb
new file mode 100644
index 0000000..c6a0042
--- /dev/null
+++ b/app/views/report/algorithm_metrics.html.erb
@@ -0,0 +1,46 @@
+
+
Percentage match is not accurate for Terms that match multiple algorithms. The actual percentage match will be lower than the reported value. At this time, the error is not believed to be significant based on the currently low volume of Terms that match multiple algorithms. This may change as we develop new algorithms to a point where we need to address this discrepancy.
+
+
+<% if params[:type] == 'aggregate' %>
+
Aggregate Algorithm Metrics
+<% else %>
+
Monthly Algorithm Metrics
+<% end %>
+
+
+
+ <% if params[:type] == 'aggregate' %>
+
Aggregation date
+ <% else %>
+
Month
+ <% end %>
+
DOI
+
ISSN
+
ISBN
+
PMID
+
Journal
+
SuggestedResource
+
Unmatched
+
% matched
+
+<% @metrics.each do |metric| %>
+
+ <% if params[:type] == 'aggregate' %>
+
<%= metric.updated_at.strftime("%d %B %Y") %>
+ <% else %>
+
<%= metric.month.strftime("%B %Y") %>
+ <% end %>
+
<%= metric.doi %>
+
<%= metric.issn %>
+
<%= metric.isbn %>
+
<%= metric.pmid %>
+
<%= metric.journal_exact %>
+
<%= metric.suggested_resource_exact %>
+
<%= metric.unmatched %>
+
+ <%= percent_match(metric) %>
+
+
+ <% end %>
+
diff --git a/app/views/report/index.html.erb b/app/views/report/index.html.erb
new file mode 100644
index 0000000..f1d8058
--- /dev/null
+++ b/app/views/report/index.html.erb
@@ -0,0 +1,6 @@
+
diff --git a/config/routes.rb b/config/routes.rb
index 7239556..ac74994 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -34,6 +34,8 @@
get 'up' => 'rails/health#show', as: :rails_health_check
get 'playground', to: 'static#playground'
+ get '/report', to: 'report#index'
+ get '/report/algorithm_metrics', to: 'report#algorithm_metrics'
# Defines the root path route ("/")
root to: 'static#index'
diff --git a/test/controllers/report_controller_test.rb b/test/controllers/report_controller_test.rb
new file mode 100644
index 0000000..f2b4608
--- /dev/null
+++ b/test/controllers/report_controller_test.rb
@@ -0,0 +1,69 @@
+require 'test_helper'
+
+class ReportControllerTest < ActionDispatch::IntegrationTest
+ test 'report index is not accessible without authentication' do
+ get '/report'
+
+ assert_redirected_to '/'
+ follow_redirect!
+
+ assert_select 'div.alert', text: 'Please sign in to continue', count: 1
+ end
+
+ test 'report index is accessible to admins when authenticated' do
+ sign_in users(:admin)
+
+ get '/report'
+
+ assert_response :success
+ end
+
+ test 'report index url is accessible to basic users when authenticated' do
+ sign_in users(:basic)
+
+ get '/report'
+
+ assert_response :success
+ end
+
+ test 'algorithm metrics report is not accessible without authentication' do
+ get '/report/algorithm_metrics'
+
+ assert_redirected_to '/'
+ follow_redirect!
+
+ assert_select 'div.alert', text: 'Please sign in to continue', count: 1
+ end
+
+ test 'algorithm metrics report is accessible to admins when authenticated' do
+ sign_in users(:admin)
+
+ get '/report/algorithm_metrics'
+
+ assert_response :success
+ end
+
+ test 'algorithm metrics report is accessible to basic users when authenticated' do
+ sign_in users(:basic)
+
+ get '/report/algorithm_metrics'
+
+ assert_response :success
+ end
+
+ test 'algorithm metrics can show monthly data' do
+ sign_in users(:basic)
+
+ get '/report/algorithm_metrics'
+
+ assert_select 'h3', text: 'Monthly Algorithm Metrics', count: 1
+ end
+
+ test 'algorithm metrics can show aggregate data' do
+ sign_in users(:basic)
+
+ get '/report/algorithm_metrics?type=aggregate'
+
+ assert_select 'h3', text: 'Aggregate Algorithm Metrics', count: 1
+ end
+end
diff --git a/test/helpers/metrics_helper_test.rb b/test/helpers/metrics_helper_test.rb
new file mode 100644
index 0000000..574f5da
--- /dev/null
+++ b/test/helpers/metrics_helper_test.rb
@@ -0,0 +1,29 @@
+require 'test_helper'
+
+class MetricsHelperTest < ActionView::TestCase
+ def metric
+ Metrics::Algorithms.new(
+ month: DateTime.now - 1.month,
+ doi: 1,
+ issn: 2,
+ isbn: 3,
+ pmid: 4,
+ unmatched: 79,
+ journal_exact: 5,
+ suggested_resource_exact: 6,
+ created_at: DateTime.now,
+ updated_at: DateTime.now
+ )
+ end
+ test 'can calculate a percentage of matches for a record' do
+ assert_in_delta(21.0, percent_match(metric), 0.01)
+ end
+
+ test 'can calculate sum of matches for a record' do
+ assert_in_delta(21.0, sum_matched(metric), 0.01)
+ end
+
+ test 'can calculate sum of all events for a record' do
+ assert_in_delta(100.0, sum_total(metric), 0.01)
+ end
+end