sufia 7.0.0.beta1 → 7.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/sufia.js +3 -4
- data/app/assets/stylesheets/sufia/_styles.scss +2 -1
- data/app/controllers/concerns/sufia/transfers_controller_behavior.rb +1 -0
- data/app/controllers/errors_controller.rb +1 -1
- data/app/indexers/sufia/work_indexer.rb +1 -0
- data/app/presenters/sufia/admin_stats_presenter.rb +17 -11
- data/app/search_builders/sufia/catalog_search_builder.rb +29 -0
- data/app/search_builders/sufia/my_collections_search_builder.rb +7 -0
- data/app/search_builders/sufia/my_highlights_search_builder.rb +9 -3
- data/app/search_builders/sufia/my_shares_search_builder.rb +8 -1
- data/app/search_builders/sufia/search_builder.rb +0 -59
- data/app/services/sufia/analytics.rb +25 -8
- data/app/services/sufia/query_service.rb +1 -1
- data/app/services/sufia/statistics/collections/over_time.rb +13 -0
- data/app/services/sufia/statistics/depositors/summary.rb +54 -0
- data/app/services/sufia/statistics/file_sets/by_format.rb +14 -0
- data/app/services/sufia/statistics/over_time.rb +11 -3
- data/app/services/sufia/statistics/system_stats.rb +61 -0
- data/app/services/sufia/statistics/term_query.rb +65 -0
- data/app/services/sufia/statistics/works/by_depositor.rb +13 -0
- data/app/services/sufia/statistics/works/by_resource_type.rb +13 -0
- data/app/services/sufia/statistics/works/count.rb +49 -0
- data/app/services/sufia/statistics/works/over_time.rb +13 -0
- data/app/views/admin/stats/_stats_by_date.html.erb +1 -1
- data/app/views/admin/stats/_top_data.html.erb +4 -4
- data/app/views/admin/stats/_works.html.erb +8 -0
- data/app/views/collections/_form.html.erb +1 -1
- data/app/views/curation_concerns/base/_attribute_rows.html.erb +10 -10
- data/app/views/curation_concerns/base/_metadata.html.erb +1 -1
- data/app/views/curation_concerns/base/_relationships.html.erb +1 -1
- data/app/views/curation_concerns/file_sets/_descriptions.html.erb +1 -1
- data/app/views/error/404.html.erb +8 -19
- data/app/views/layouts/error.html.erb +3 -3
- data/app/views/layouts/homepage.html.erb +1 -1
- data/app/views/layouts/sufia-dashboard.html.erb +1 -1
- data/app/views/layouts/sufia-one-column.html.erb +1 -1
- data/app/views/{_footer.html.erb → shared/_footer.html.erb} +1 -1
- data/app/views/stats/file.html.erb +0 -1
- data/app/views/stats/work.html.erb +0 -2
- data/lib/generators/sufia/install_generator.rb +6 -0
- data/lib/sufia/engine.rb +1 -0
- data/lib/sufia/version.rb +1 -1
- data/spec/controllers/my/shares_controller_spec.rb +6 -7
- data/spec/controllers/transfers_controller_spec.rb +10 -0
- data/spec/features/batch_edit_spec.rb +1 -1
- data/spec/lib/sufia/analytics_spec.rb +18 -10
- data/spec/presenters/sufia/admin_stats_presenter_spec.rb +21 -14
- data/spec/search_builder/{sufia_search_builder_spec.rb → sufia/catalog_search_builder_spec.rb} +1 -1
- data/spec/search_builder/sufia/my_shares_search_builder_spec.rb +18 -0
- data/spec/services/statistics/{collections_spec.rb → collections/over_time_spec.rb} +1 -1
- data/spec/services/{sufia/admin/depositor_stats_spec.rb → statistics/depositors/summary_spec.rb} +5 -7
- data/spec/services/statistics/file_sets/by_format_spec.rb +30 -0
- data/spec/services/statistics/system_stats_spec.rb +54 -0
- data/spec/services/statistics/works/by_depositor_spec.rb +25 -0
- data/spec/services/statistics/works/by_resource_type_spec.rb +21 -0
- data/spec/services/statistics/works/count_spec.rb +42 -0
- data/spec/services/statistics/{works_spec.rb → works/over_time_spec.rb} +1 -1
- data/spec/views/admin/stats/index.html.erb_spec.rb +3 -6
- data/spec/views/curation_concerns/base/_relationships.html.erb_spec.rb +4 -1
- data/sufia.gemspec +2 -1
- metadata +49 -25
- data/app/services/sufia/admin/depositor_stats.rb +0 -48
- data/app/services/sufia/statistics/collections.rb +0 -12
- data/app/services/sufia/statistics/works.rb +0 -12
- data/app/services/sufia/system_stats.rb +0 -120
- data/app/views/admin/stats/_files.html.erb +0 -8
- data/lib/generators/sufia/fulltext_generator.rb +0 -26
- data/spec/services/sufia/system_stats_spec.rb +0 -224
- data/vendor/assets/javascripts/flot/excanvas.js +0 -1428
- data/vendor/assets/javascripts/flot/jquery.flot.js +0 -3168
- data/vendor/assets/javascripts/flot/jquery.flot.selection.js +0 -360
- data/vendor/assets/javascripts/flot/jquery.flot.time.js +0 -432
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8878efdf23b664d1ccc522e05f997d099dcd43f9
|
4
|
+
data.tar.gz: 8062a829e1bc496ef751aca11363c10bc5fc143c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1457e174fcfdf5ceb54dc2c9090a37bb03af3c47882f04a046550f19b1687112cfd073ac9b75199ad4db8615ab13790b5ed47ee39772a582b3299dc3070fa82
|
7
|
+
data.tar.gz: afdcc985bc2f96201032af0c9ef78ceb2eb7387499ad0621c775fcfbd0d6a24e315b619fba59cfa2503432d626dcc209cffc754a6498f548091cac415338c9b1
|
@@ -21,10 +21,9 @@
|
|
21
21
|
//= require select2
|
22
22
|
//= require fixedsticky
|
23
23
|
|
24
|
-
//= require flot
|
25
|
-
//= require
|
26
|
-
//= require
|
27
|
-
//= require flot/jquery.flot.selection
|
24
|
+
//= require jquery.flot
|
25
|
+
//= require jquery.flot.time
|
26
|
+
//= require jquery.flot.selection
|
28
27
|
|
29
28
|
//= require batch_edit
|
30
29
|
//
|
@@ -3,6 +3,7 @@ module Sufia
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
before_action :authenticate_user!
|
6
7
|
before_action :load_proxy_deposit_request, only: :create
|
7
8
|
load_and_authorize_resource :proxy_deposit_request, parent: false, except: :index
|
8
9
|
before_action :authorize_depositor_by_id, only: [:new, :create]
|
@@ -7,6 +7,6 @@ class ErrorsController < ApplicationController
|
|
7
7
|
|
8
8
|
def render_routing_error(exception)
|
9
9
|
logger.error("Rendering 404 page due to exception: #{exception.inspect} - #{exception.backtrace if exception.respond_to? :backtrace}")
|
10
|
-
render
|
10
|
+
render '404', layout: "error", status: 404
|
11
11
|
end
|
12
12
|
end
|
@@ -7,6 +7,7 @@ module Sufia
|
|
7
7
|
# the search query. While at the same time allowing us not to return Collections
|
8
8
|
# when a work in the collection matches the query.
|
9
9
|
solr_doc[Solrizer.solr_name('file_set_ids', :symbol)] = solr_doc[Solrizer.solr_name('member_ids', :symbol)]
|
10
|
+
solr_doc[Solrizer.solr_name('resource_type', :facetable)] = object.resource_type
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
@@ -1,16 +1,22 @@
|
|
1
1
|
module Sufia
|
2
2
|
class AdminStatsPresenter
|
3
|
-
attr_reader :limit, :
|
3
|
+
attr_reader :limit, :stats_filters
|
4
4
|
|
5
5
|
def initialize(stats_filters, limit)
|
6
6
|
@stats_filters = stats_filters
|
7
|
-
@start_date = stats_filters[:start_date]
|
8
|
-
@end_date = stats_filters[:end_date]
|
9
7
|
@limit = limit
|
10
8
|
end
|
11
9
|
|
10
|
+
def start_date
|
11
|
+
@start_date ||= Time.zone.parse(stats_filters[:start_date]).beginning_of_day if stats_filters[:start_date].present?
|
12
|
+
end
|
13
|
+
|
14
|
+
def end_date
|
15
|
+
@end_date ||= Time.zone.parse(stats_filters[:end_date]).end_of_day if stats_filters[:end_date].present?
|
16
|
+
end
|
17
|
+
|
12
18
|
def depositors
|
13
|
-
@depositors ||= Sufia::
|
19
|
+
@depositors ||= Sufia::Statistics::Depositors::Summary.new(start_date, end_date).depositors
|
14
20
|
end
|
15
21
|
|
16
22
|
def recent_users
|
@@ -18,15 +24,15 @@ module Sufia
|
|
18
24
|
end
|
19
25
|
|
20
26
|
def active_users
|
21
|
-
@active_users ||=
|
27
|
+
@active_users ||= Sufia::Statistics::Works::ByDepositor.new(limit).query
|
22
28
|
end
|
23
29
|
|
24
30
|
def top_formats
|
25
|
-
@top_formats ||=
|
31
|
+
@top_formats ||= Sufia::Statistics::FileSets::ByFormat.new(limit).query
|
26
32
|
end
|
27
33
|
|
28
|
-
def
|
29
|
-
@
|
34
|
+
def works_count
|
35
|
+
@works_count ||= Sufia::Statistics::Works::Count.new(start_date, end_date).by_permission
|
30
36
|
end
|
31
37
|
|
32
38
|
def users_count
|
@@ -37,16 +43,16 @@ module Sufia
|
|
37
43
|
if start_date.blank?
|
38
44
|
"unfiltered"
|
39
45
|
elsif end_date.blank?
|
40
|
-
"#{start_date} to #{Date.current}"
|
46
|
+
"#{start_date.to_date.to_formatted_s(:standard)} to #{Date.current.to_formatted_s(:standard)}"
|
41
47
|
else
|
42
|
-
"#{start_date} to #{end_date}"
|
48
|
+
"#{start_date.to_date.to_formatted_s(:standard)} to #{end_date.to_date.to_formatted_s(:standard)}"
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
52
|
private
|
47
53
|
|
48
54
|
def stats
|
49
|
-
@stats ||= SystemStats.new(limit, start_date, end_date)
|
55
|
+
@stats ||= Sufia::Statistics::SystemStats.new(limit, start_date, end_date)
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
@@ -4,4 +4,33 @@ class Sufia::CatalogSearchBuilder < Sufia::SearchBuilder
|
|
4
4
|
:add_advanced_parse_q_to_solr,
|
5
5
|
:show_works_or_works_that_contain_files
|
6
6
|
]
|
7
|
+
|
8
|
+
# show both works that match the query and works that contain files that match the query
|
9
|
+
def show_works_or_works_that_contain_files(solr_parameters)
|
10
|
+
return if solr_parameters[:q].blank?
|
11
|
+
solr_parameters[:user_query] = solr_parameters[:q]
|
12
|
+
solr_parameters[:q] = new_query
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# the {!lucene} gives us the OR syntax
|
18
|
+
def new_query
|
19
|
+
"{!lucene}#{interal_query(dismax_query)} #{interal_query(join_for_works_from_files)}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# the _query_ allows for another parser (aka dismax)
|
23
|
+
def interal_query(query_value)
|
24
|
+
"_query_:\"#{query_value}\""
|
25
|
+
end
|
26
|
+
|
27
|
+
# the {!dismax} causes the query to go against the query fields
|
28
|
+
def dismax_query
|
29
|
+
"{!dismax v=$user_query}"
|
30
|
+
end
|
31
|
+
|
32
|
+
# join from file id to work relationship solrized file_set_ids_ssim
|
33
|
+
def join_for_works_from_files
|
34
|
+
"{!join from=#{ActiveFedora.id_field} to=file_set_ids_ssim}#{dismax_query}"
|
35
|
+
end
|
7
36
|
end
|
@@ -6,4 +6,11 @@ class Sufia::MyCollectionsSearchBuilder < Sufia::SearchBuilder
|
|
6
6
|
:show_only_resources_deposited_by_current_user,
|
7
7
|
:show_only_collections
|
8
8
|
]
|
9
|
+
|
10
|
+
def show_only_collections(solr_parameters)
|
11
|
+
solr_parameters[:fq] ||= []
|
12
|
+
solr_parameters[:fq] += [
|
13
|
+
ActiveFedora::SolrQueryBuilder.construct_query_for_rel(has_model: Collection.to_class_uri)
|
14
|
+
]
|
15
|
+
end
|
9
16
|
end
|
@@ -2,7 +2,13 @@
|
|
2
2
|
class Sufia::MyHighlightsSearchBuilder < Sufia::SearchBuilder
|
3
3
|
include Sufia::MySearchBuilderBehavior
|
4
4
|
|
5
|
-
self.default_processor_chain += [
|
6
|
-
|
7
|
-
|
5
|
+
self.default_processor_chain += [:show_only_highlighted_works]
|
6
|
+
|
7
|
+
def show_only_highlighted_works(solr_parameters)
|
8
|
+
ids = scope.current_user.trophies.pluck(:work_id)
|
9
|
+
solr_parameters[:fq] ||= []
|
10
|
+
solr_parameters[:fq] += [
|
11
|
+
ActiveFedora::SolrQueryBuilder.construct_query_for_ids(ids)
|
12
|
+
]
|
13
|
+
end
|
8
14
|
end
|
@@ -2,5 +2,12 @@
|
|
2
2
|
class Sufia::MySharesSearchBuilder < Sufia::SearchBuilder
|
3
3
|
include Sufia::MySearchBuilderBehavior
|
4
4
|
|
5
|
-
self.default_processor_chain
|
5
|
+
self.default_processor_chain += [:show_only_shared_files]
|
6
|
+
|
7
|
+
def show_only_shared_files(solr_parameters)
|
8
|
+
solr_parameters[:fq] ||= []
|
9
|
+
solr_parameters[:fq] += [
|
10
|
+
"-" + ActiveFedora::SolrQueryBuilder.construct_query_for_rel(depositor: scope.current_user.user_key)
|
11
|
+
]
|
12
|
+
end
|
6
13
|
end
|
@@ -4,13 +4,6 @@ class Sufia::SearchBuilder < Blacklight::SearchBuilder
|
|
4
4
|
include Hydra::AccessControlsEnforcement
|
5
5
|
include CurationConcerns::SearchFilters
|
6
6
|
|
7
|
-
def show_only_collections(solr_parameters)
|
8
|
-
solr_parameters[:fq] ||= []
|
9
|
-
solr_parameters[:fq] += [
|
10
|
-
ActiveFedora::SolrQueryBuilder.construct_query_for_rel(has_model: Collection.to_class_uri)
|
11
|
-
]
|
12
|
-
end
|
13
|
-
|
14
7
|
def show_only_resources_deposited_by_current_user(solr_parameters)
|
15
8
|
solr_parameters[:fq] ||= []
|
16
9
|
solr_parameters[:fq] += [
|
@@ -24,56 +17,4 @@ class Sufia::SearchBuilder < Blacklight::SearchBuilder
|
|
24
17
|
ActiveFedora::SolrQueryBuilder.construct_query_for_rel(has_model: ::GenericWork.to_class_uri)
|
25
18
|
]
|
26
19
|
end
|
27
|
-
|
28
|
-
def show_only_shared_files(solr_parameters)
|
29
|
-
solr_parameters[:fq] ||= []
|
30
|
-
solr_parameters[:fq] += [
|
31
|
-
"-" + ActiveFedora::SolrQueryBuilder.construct_query_for_rel(depositor: scope.current_user.user_key)
|
32
|
-
]
|
33
|
-
end
|
34
|
-
|
35
|
-
def show_only_highlighted_works(solr_parameters)
|
36
|
-
ids = scope.current_user.trophies.pluck(:work_id)
|
37
|
-
solr_parameters[:fq] ||= []
|
38
|
-
solr_parameters[:fq] += [
|
39
|
-
ActiveFedora::SolrQueryBuilder.construct_query_for_ids(ids)
|
40
|
-
]
|
41
|
-
end
|
42
|
-
|
43
|
-
# Limits search results just to GenericWorks and collections
|
44
|
-
# @param solr_parameters the current solr parameters
|
45
|
-
# @param user_parameters the current user-submitted parameters
|
46
|
-
def only_works_and_collections(solr_parameters)
|
47
|
-
solr_parameters[:fq] ||= []
|
48
|
-
solr_parameters[:fq] << "#{Solrizer.solr_name('has_model', :symbol)}:(\"GenericWork\" \"Collection\")"
|
49
|
-
end
|
50
|
-
|
51
|
-
# show both works that match the query and works that contain files that match the query
|
52
|
-
def show_works_or_works_that_contain_files(solr_parameters)
|
53
|
-
return if solr_parameters[:q].blank?
|
54
|
-
solr_parameters[:user_query] = solr_parameters[:q]
|
55
|
-
solr_parameters[:q] = new_query
|
56
|
-
end
|
57
|
-
|
58
|
-
protected
|
59
|
-
|
60
|
-
# the {!lucene} gives us the OR syntax
|
61
|
-
def new_query
|
62
|
-
"{!lucene}#{interal_query(dismax_query)} #{interal_query(join_for_works_from_files)}"
|
63
|
-
end
|
64
|
-
|
65
|
-
# the _query_ allows for another parser (aka dismax)
|
66
|
-
def interal_query(query_value)
|
67
|
-
"_query_:\"#{query_value}\""
|
68
|
-
end
|
69
|
-
|
70
|
-
# the {!dismax} causes the query to go against the query fields
|
71
|
-
def dismax_query
|
72
|
-
"{!dismax v=$user_query}"
|
73
|
-
end
|
74
|
-
|
75
|
-
# join from file id to work relationship solrized file_set_ids_ssim
|
76
|
-
def join_for_works_from_files
|
77
|
-
"{!join from=#{ActiveFedora.id_field} to=file_set_ids_ssim}#{dismax_query}"
|
78
|
-
end
|
79
20
|
end
|
@@ -13,30 +13,47 @@ module Sufia
|
|
13
13
|
# ` client_email: GOOGLE_OAUTH_CLIENT_EMAIL`
|
14
14
|
# @return [Hash] A hash containing five keys: 'app_name', 'app_version', 'client_email', 'privkey_path', 'privkey_secret'
|
15
15
|
def self.config
|
16
|
-
@config ||=
|
16
|
+
@config ||= load_config
|
17
17
|
end
|
18
|
+
private_class_method :config
|
19
|
+
|
20
|
+
def self.load_config
|
21
|
+
filename = File.join(Rails.root, 'config', 'analytics.yml')
|
22
|
+
yaml = YAML.load(File.read(filename))
|
23
|
+
unless yaml
|
24
|
+
Rails.logger.error("Unable to fetch any keys from #{filename}.")
|
25
|
+
return
|
26
|
+
end
|
27
|
+
yaml.fetch('analytics')
|
28
|
+
end
|
29
|
+
private_class_method :load_config
|
18
30
|
|
19
31
|
# Generate an OAuth2 token for Google Analytics
|
20
32
|
# @return [OAuth2::AccessToken] An OAuth2 access token for GA
|
21
33
|
def self.token
|
22
34
|
scope = 'https://www.googleapis.com/auth/analytics.readonly'
|
23
|
-
client = Google::APIClient.new(application_name: config
|
24
|
-
application_version: config
|
25
|
-
key = Google::APIClient::PKCS12.load_key(config
|
26
|
-
config
|
27
|
-
service_account = Google::APIClient::JWTAsserter.new(config
|
35
|
+
client = Google::APIClient.new(application_name: config.fetch('app_name'),
|
36
|
+
application_version: config.fetch('app_version'))
|
37
|
+
key = Google::APIClient::PKCS12.load_key(config.fetch('privkey_path'),
|
38
|
+
config.fetch('privkey_secret'))
|
39
|
+
service_account = Google::APIClient::JWTAsserter.new(config.fetch('client_email'),
|
40
|
+
scope,
|
28
41
|
key)
|
29
42
|
client.authorization = service_account.authorize
|
30
|
-
oauth_client = OAuth2::Client.new('',
|
31
|
-
|
43
|
+
oauth_client = OAuth2::Client.new('',
|
44
|
+
'',
|
45
|
+
authorize_url: 'https://accounts.google.com/o/oauth2/auth',
|
46
|
+
token_url: 'https://accounts.google.com/o/oauth2/token')
|
32
47
|
OAuth2::AccessToken.new(oauth_client, client.authorization.access_token)
|
33
48
|
end
|
49
|
+
private_class_method :token
|
34
50
|
|
35
51
|
# Return a user object linked to a Google Analytics account
|
36
52
|
# @return [Legato::User] A user account wit GA access
|
37
53
|
def self.user
|
38
54
|
Legato::User.new(token)
|
39
55
|
end
|
56
|
+
private_class_method :user
|
40
57
|
|
41
58
|
# Return a Google Analytics profile matching specified ID
|
42
59
|
# @ return [Legato::Management::Profile] A user profile associated with GA
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Sufia
|
2
2
|
class QueryService
|
3
|
-
# query to find
|
3
|
+
# query to find works created during the time range
|
4
4
|
# @param [DateTime] start_datetime starting date time for range query
|
5
5
|
# @param [DateTime] end_datetime ending date time for range query
|
6
6
|
def find_by_date_created(start_datetime, end_datetime = nil)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Gather information about the depositors who have contributed to the repository
|
2
|
+
module Sufia
|
3
|
+
module Statistics
|
4
|
+
module Depositors
|
5
|
+
class Summary
|
6
|
+
include Blacklight::SearchHelper
|
7
|
+
|
8
|
+
# @param [Time] start_date optionally specify the start date to gather the stats from
|
9
|
+
# @param [Time] end_date optionally specify the end date to gather the stats from
|
10
|
+
def initialize(start_date, end_date)
|
11
|
+
@start_dt = start_date
|
12
|
+
@end_dt = end_date
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :start_dt, :end_dt
|
16
|
+
|
17
|
+
def depositors
|
18
|
+
# step through the array by twos to get each pair
|
19
|
+
results.map do |key, deposits|
|
20
|
+
user = ::User.find_by_user_key(key)
|
21
|
+
{ key: key, deposits: deposits, user: user }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
delegate :blacklight_config, to: CatalogController
|
28
|
+
delegate :depositor_field, to: DepositSearchBuilder
|
29
|
+
|
30
|
+
# results come from Solr in an array where the first item is the user and
|
31
|
+
# the second item is the count
|
32
|
+
# [ abc123, 55, ccczzz, 205 ]
|
33
|
+
# @return [#each] an enumerable object of tuples (user and count)
|
34
|
+
def results
|
35
|
+
facet_results = repository.search(query)
|
36
|
+
facet_results.facet_fields[depositor_field].each_slice(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
def search_builder
|
40
|
+
DepositSearchBuilder.new([:include_depositor_facet], self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: This can probably be pushed into the DepositSearchBuilder
|
44
|
+
def query
|
45
|
+
search_builder.merge(q: date_query).query
|
46
|
+
end
|
47
|
+
|
48
|
+
def date_query
|
49
|
+
Sufia::QueryService.new.build_date_query(start_dt, end_dt) unless start_dt.blank?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Sufia
|
2
2
|
module Statistics
|
3
3
|
# An abstract class for generating cumulative graphs
|
4
|
-
# you must provide a `
|
4
|
+
# you must provide a `relation` method in the concrete class
|
5
5
|
class OverTime
|
6
6
|
# @param [Fixnum] delta_x change in x (in days)
|
7
7
|
# @param [Time] x_min minimum date
|
@@ -24,12 +24,20 @@ module Sufia
|
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
+
def point(min, max)
|
28
|
+
relation.where(query(min, max)).count
|
29
|
+
end
|
30
|
+
|
31
|
+
def query(min, max)
|
32
|
+
QueryService.new.build_date_query(min, max)
|
33
|
+
end
|
34
|
+
|
27
35
|
def size
|
28
36
|
((@x_max - @x_min) / @delta_x.days.to_i).ceil
|
29
37
|
end
|
30
38
|
|
31
|
-
def
|
32
|
-
raise NotImplementedError, "Implement the
|
39
|
+
def relation
|
40
|
+
raise NotImplementedError, "Implement the relation method in a concrete class"
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|