sufia 7.0.0.beta1 → 7.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/sufia.js +3 -4
  3. data/app/assets/stylesheets/sufia/_styles.scss +2 -1
  4. data/app/controllers/concerns/sufia/transfers_controller_behavior.rb +1 -0
  5. data/app/controllers/errors_controller.rb +1 -1
  6. data/app/indexers/sufia/work_indexer.rb +1 -0
  7. data/app/presenters/sufia/admin_stats_presenter.rb +17 -11
  8. data/app/search_builders/sufia/catalog_search_builder.rb +29 -0
  9. data/app/search_builders/sufia/my_collections_search_builder.rb +7 -0
  10. data/app/search_builders/sufia/my_highlights_search_builder.rb +9 -3
  11. data/app/search_builders/sufia/my_shares_search_builder.rb +8 -1
  12. data/app/search_builders/sufia/search_builder.rb +0 -59
  13. data/app/services/sufia/analytics.rb +25 -8
  14. data/app/services/sufia/query_service.rb +1 -1
  15. data/app/services/sufia/statistics/collections/over_time.rb +13 -0
  16. data/app/services/sufia/statistics/depositors/summary.rb +54 -0
  17. data/app/services/sufia/statistics/file_sets/by_format.rb +14 -0
  18. data/app/services/sufia/statistics/over_time.rb +11 -3
  19. data/app/services/sufia/statistics/system_stats.rb +61 -0
  20. data/app/services/sufia/statistics/term_query.rb +65 -0
  21. data/app/services/sufia/statistics/works/by_depositor.rb +13 -0
  22. data/app/services/sufia/statistics/works/by_resource_type.rb +13 -0
  23. data/app/services/sufia/statistics/works/count.rb +49 -0
  24. data/app/services/sufia/statistics/works/over_time.rb +13 -0
  25. data/app/views/admin/stats/_stats_by_date.html.erb +1 -1
  26. data/app/views/admin/stats/_top_data.html.erb +4 -4
  27. data/app/views/admin/stats/_works.html.erb +8 -0
  28. data/app/views/collections/_form.html.erb +1 -1
  29. data/app/views/curation_concerns/base/_attribute_rows.html.erb +10 -10
  30. data/app/views/curation_concerns/base/_metadata.html.erb +1 -1
  31. data/app/views/curation_concerns/base/_relationships.html.erb +1 -1
  32. data/app/views/curation_concerns/file_sets/_descriptions.html.erb +1 -1
  33. data/app/views/error/404.html.erb +8 -19
  34. data/app/views/layouts/error.html.erb +3 -3
  35. data/app/views/layouts/homepage.html.erb +1 -1
  36. data/app/views/layouts/sufia-dashboard.html.erb +1 -1
  37. data/app/views/layouts/sufia-one-column.html.erb +1 -1
  38. data/app/views/{_footer.html.erb → shared/_footer.html.erb} +1 -1
  39. data/app/views/stats/file.html.erb +0 -1
  40. data/app/views/stats/work.html.erb +0 -2
  41. data/lib/generators/sufia/install_generator.rb +6 -0
  42. data/lib/sufia/engine.rb +1 -0
  43. data/lib/sufia/version.rb +1 -1
  44. data/spec/controllers/my/shares_controller_spec.rb +6 -7
  45. data/spec/controllers/transfers_controller_spec.rb +10 -0
  46. data/spec/features/batch_edit_spec.rb +1 -1
  47. data/spec/lib/sufia/analytics_spec.rb +18 -10
  48. data/spec/presenters/sufia/admin_stats_presenter_spec.rb +21 -14
  49. data/spec/search_builder/{sufia_search_builder_spec.rb → sufia/catalog_search_builder_spec.rb} +1 -1
  50. data/spec/search_builder/sufia/my_shares_search_builder_spec.rb +18 -0
  51. data/spec/services/statistics/{collections_spec.rb → collections/over_time_spec.rb} +1 -1
  52. data/spec/services/{sufia/admin/depositor_stats_spec.rb → statistics/depositors/summary_spec.rb} +5 -7
  53. data/spec/services/statistics/file_sets/by_format_spec.rb +30 -0
  54. data/spec/services/statistics/system_stats_spec.rb +54 -0
  55. data/spec/services/statistics/works/by_depositor_spec.rb +25 -0
  56. data/spec/services/statistics/works/by_resource_type_spec.rb +21 -0
  57. data/spec/services/statistics/works/count_spec.rb +42 -0
  58. data/spec/services/statistics/{works_spec.rb → works/over_time_spec.rb} +1 -1
  59. data/spec/views/admin/stats/index.html.erb_spec.rb +3 -6
  60. data/spec/views/curation_concerns/base/_relationships.html.erb_spec.rb +4 -1
  61. data/sufia.gemspec +2 -1
  62. metadata +49 -25
  63. data/app/services/sufia/admin/depositor_stats.rb +0 -48
  64. data/app/services/sufia/statistics/collections.rb +0 -12
  65. data/app/services/sufia/statistics/works.rb +0 -12
  66. data/app/services/sufia/system_stats.rb +0 -120
  67. data/app/views/admin/stats/_files.html.erb +0 -8
  68. data/lib/generators/sufia/fulltext_generator.rb +0 -26
  69. data/spec/services/sufia/system_stats_spec.rb +0 -224
  70. data/vendor/assets/javascripts/flot/excanvas.js +0 -1428
  71. data/vendor/assets/javascripts/flot/jquery.flot.js +0 -3168
  72. data/vendor/assets/javascripts/flot/jquery.flot.selection.js +0 -360
  73. data/vendor/assets/javascripts/flot/jquery.flot.time.js +0 -432
@@ -0,0 +1,61 @@
1
+ module Sufia
2
+ module Statistics
3
+ # A class that retrieves system level statistics about the system
4
+ # TODO: this class could be refactored into several classes.
5
+ #
6
+ # @attr_reader [Integer] limit limits the results returned from top_depositors and top_formats
7
+ # Default is 5, maximum is 20, minimum is 5
8
+ # @attr_reader [Time] start_date Filters the statistics returned by the class to after the start date
9
+ # nil means no filter
10
+ # @attr_reader [Time] end_date Filters the statistics returned by the class to before end date
11
+ # nil means today
12
+ class SystemStats
13
+ attr_reader :limit, :start_date, :end_date
14
+
15
+ # @param [Fixnum] limit_records limits the results returned from top_depositors and top_formats. Maximum is 20, minimum is 5
16
+ # @param [Time] start_date Filters the statistics returned by the class to after this date. nil means no filter
17
+ # @param [Time] end_date Filters the statistics returned by the class to before this date. nil means today
18
+ def initialize(limit_records = 5, start_date = nil, end_date = nil)
19
+ @limit = validate_limit(limit_records)
20
+ @start_date = start_date
21
+ @end_date = end_date
22
+ end
23
+
24
+ # returns a list (of size limit) of system users (depositors) that have the most deposits in the system
25
+ # @return [Hash] a hash with the user name as the key and the number of deposits as the value
26
+ # { 'cam156' => 25, 'hjc14' => 24 ... }
27
+ def top_depositors
28
+ TermQuery.new(limit).results(depositor_field)
29
+ end
30
+
31
+ delegate :depositor_field, to: DepositSearchBuilder
32
+
33
+ # returns [Array<user>] a list (of size limit) of users most recently registered with the system
34
+ #
35
+ def recent_users
36
+ # no dates return the top few based on limit
37
+ return ::User.order('created_at DESC').limit(limit) if start_date.blank?
38
+
39
+ ::User.recent_users start_date, end_date
40
+ end
41
+
42
+ # returns [Number] the number of currently registered users
43
+ #
44
+ def users_count
45
+ ::User.count
46
+ end
47
+
48
+ private
49
+
50
+ def validate_limit(count)
51
+ if count.blank? || count < 5
52
+ 5
53
+ elsif count > 20
54
+ 20
55
+ else
56
+ count
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,65 @@
1
+ module Sufia
2
+ module Statistics
3
+ # An abstract class for running a query against the Solr terms component
4
+ # you must implement `index_key` in the concrete class.
5
+ #
6
+ # WARNING: you must use a term that isn't parsed (i.e. use _sim instead of _tesim)
7
+ class TermQuery
8
+ def initialize(limit = 5)
9
+ @limit = limit
10
+ end
11
+
12
+ def query
13
+ term = index_key
14
+ # Grab JSON response (looks like {"terms": {"depositor_tesim": {"mjg36": 3}}} for depositor)
15
+ json = solr_connection.get 'terms', params: { 'terms.fl' => term,
16
+ 'terms.sort' => 'count',
17
+ 'terms.limit' => @limit,
18
+ wt: 'json',
19
+ 'json.nl' => 'map',
20
+ omitHeader: 'true' }
21
+ unless json
22
+ Rails.logger.error "Unable to reach TermsComponent via Solr connection. Is it enabled in your solr config?"
23
+ return []
24
+ end
25
+
26
+ Result.build(json['terms'][term])
27
+ end
28
+
29
+ class Result
30
+ # @param [Array<Array>] rows list of of tuples (label, value)
31
+ def self.build(rows)
32
+ rows.map { |row| Result.new(*row) }
33
+ end
34
+
35
+ def initialize(label, value)
36
+ @data = { label: label, data: value }
37
+ end
38
+
39
+ def label
40
+ @data[:label]
41
+ end
42
+
43
+ def value
44
+ @data[:data]
45
+ end
46
+
47
+ # This enables hash equivalence
48
+ def ==(other)
49
+ other == @data
50
+ end
51
+
52
+ # Allows us to create a Flot charts pie-graph
53
+ def as_json(opts)
54
+ @data.as_json(opts)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def solr_connection
61
+ ActiveFedora::SolrService.instance.conn
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ module Sufia
2
+ module Statistics
3
+ module Works
4
+ class ByDepositor < Statistics::TermQuery
5
+ private
6
+
7
+ def index_key
8
+ DepositSearchBuilder.depositor_field
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Sufia
2
+ module Statistics
3
+ module Works
4
+ class ByResourceType < Statistics::TermQuery
5
+ private
6
+
7
+ def index_key
8
+ Solrizer.solr_name("resource_type", :facetable)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ module Sufia
2
+ module Statistics
3
+ module Works
4
+ class Count
5
+ attr_reader :start_date, :end_date
6
+
7
+ # @param [Time] start_date Filters the statistics returned by the class to after this date. nil means no filter
8
+ # @param [Time] end_date Filters the statistics returned by the class to before this date. nil means today
9
+ def initialize(start_date = nil, end_date = nil)
10
+ @start_date = start_date
11
+ @end_date = end_date
12
+ end
13
+
14
+ # Retrieves the count of works in the system filtered by the start_date and end_date if present
15
+ #
16
+ # @return [Hash] A hash with the total files by permission for the system
17
+ # @option [Number] :total Total number of files without regard to permissions
18
+ # @option [Number] :public Total number of files that have public permissions
19
+ # @option [Number] :registered Total number of files that have registered (logged in) permissions
20
+ # @option [Number] :private Total number of files that have private permissions
21
+ def by_permission
22
+ return by_date_and_permission if start_date
23
+
24
+ works_count = {}
25
+ works_count[:total] = query_service.count
26
+ works_count[:public] = query_service.where_public.count
27
+ works_count[:registered] = query_service.where_registered.count
28
+ works_count[:private] = works_count[:total] - (works_count[:registered] + works_count[:public])
29
+ works_count
30
+ end
31
+
32
+ private
33
+
34
+ def query_service
35
+ @query_service ||= Sufia::QueryService.new
36
+ end
37
+
38
+ def by_date_and_permission
39
+ works_count = {}
40
+ works_count[:total] = query_service.find_by_date_created(start_date, end_date).count
41
+ works_count[:public] = query_service.find_public_in_date_range(start_date, end_date).count
42
+ works_count[:registered] = query_service.find_registered_in_date_range(start_date, end_date).count
43
+ works_count[:private] = works_count[:total] - (works_count[:registered] + works_count[:public])
44
+ works_count
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ module Sufia
2
+ module Statistics
3
+ module Works
4
+ class OverTime < Statistics::OverTime
5
+ private
6
+
7
+ def relation
8
+ CurationConcerns::WorkRelation.new
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,6 +3,6 @@
3
3
  The data is unfiltered unless the date form has been filled in. Start date is required and the default end is now.
4
4
  </p>
5
5
  <%= render "admin/stats/date_form" %>
6
- <%= render "admin/stats/files" %>
6
+ <%= render "admin/stats/works" %>
7
7
  <%= render "admin/stats/new_users" %>
8
8
  <%= render "admin/stats/deposits" %>
@@ -8,17 +8,17 @@
8
8
 
9
9
  <h3>Top File Formats (top <%= @presenter.top_formats.count %>)</h3>
10
10
  <ul>
11
- <% @presenter.top_formats.each do |k, v| %>
12
- <li><%= k %> <span class="count">(<%= v %>)</span></li>
11
+ <% @presenter.top_formats.each do |fmt| %>
12
+ <li><%= fmt.label %> <span class="count">(<%= fmt.value %>)</span></li>
13
13
  <% end %>
14
14
  </ul>
15
15
 
16
16
  <br/>
17
17
  <h3>Most Active Users (top <%= @presenter.active_users.count %>)</h3>
18
18
  <ul>
19
- <% @presenter.active_users.each do |k, v| %>
19
+ <% @presenter.active_users.each do |user| %>
20
20
  <li>
21
- <%= link_to_profile(k) %> <span class="count">(<%= v %>)</span>
21
+ <%= link_to_profile(user.label) %> <span class="count">(<%= user.value %>)</span>
22
22
  </li>
23
23
  <% end %>
24
24
  </ul>
@@ -0,0 +1,8 @@
1
+ <h3>Work Statistics (<%= @presenter.date_filter_string %>)</h3>
2
+ <h4>Total Works: <%= @presenter.works_count[:total] %> </h4>
3
+ <h4>Totals by Visibility</h4>
4
+ <ul>
5
+ <li>Open Access <span class="count">(<%= @presenter.works_count[:public] %>)</span></li>
6
+ <li><%= t("sufia.admin.stats.registered") %> <span class="count">(<%= @presenter.works_count[:registered] %>)</span></li>
7
+ <li>Private <span class="count">(<%= @presenter.works_count[:private] %>)</span></li>
8
+ </ul>
@@ -1,6 +1,6 @@
1
1
  <%= simple_form_for @form, html: { class: 'editor' } do |f| %>
2
2
  <div id="descriptions_display">
3
- <h2 class="non lower">Descriptions <small class="pull-right"><span class="error">*</span> indicates required fields</small> </h2>
3
+ <h2 class="non lower">Descriptions</h2>
4
4
  <% f.object.rendered_terms.each do |term| %>
5
5
  <%= render_edit_field_partial term, f: f %>
6
6
  <% end %>
@@ -1,11 +1,11 @@
1
- <%= presenter.attribute_to_html(:creator, catalog_search_link: true ) %>
2
- <%= presenter.attribute_to_html(:contributor, label: 'Contributors', catalog_search_link: true) %>
3
- <%= presenter.attribute_to_html(:subject, catalog_search_link: true) %>
4
- <%= presenter.attribute_to_html(:publisher) %>
5
- <%= presenter.attribute_to_html(:language) %>
6
- <%= presenter.attribute_to_html(:identifier) %>
7
- <%= presenter.attribute_to_html(:keyword) %>
8
- <%= presenter.attribute_to_html(:date_created) %>
9
- <%= presenter.attribute_to_html(:based_near) %>
1
+ <%= presenter.attribute_to_html(:creator, render_as: :faceted ) %>
2
+ <%= presenter.attribute_to_html(:contributor, label: 'Contributors', render_as: :faceted) %>
3
+ <%= presenter.attribute_to_html(:subject, render_as: :faceted ) %>
4
+ <%= presenter.attribute_to_html(:publisher, render_as: :faceted ) %>
5
+ <%= presenter.attribute_to_html(:language, render_as: :faceted ) %>
6
+ <%= presenter.attribute_to_html(:identifier, render_as: :linked, search_field: 'identifier_tesim') %>
7
+ <%= presenter.attribute_to_html(:keyword, render_as: :faceted ) %>
8
+ <%= presenter.attribute_to_html(:date_created, render_as: :linked, search_field: 'date_created_tesim' ) %>
9
+ <%= presenter.attribute_to_html(:based_near, render_as: :faceted ) %>
10
10
  <%= presenter.attribute_to_html(:related_url) %>
11
- <%= presenter.attribute_to_html(:resource_type) %>
11
+ <%= presenter.attribute_to_html(:resource_type, render_as: :faceted ) %>
@@ -7,6 +7,6 @@
7
7
  <%= render 'attribute_rows', presenter: presenter %>
8
8
  <%= presenter.attribute_to_html(:embargo_release_date) %>
9
9
  <%= presenter.attribute_to_html(:lease_expiration_date) %>
10
- <%= presenter.attribute_to_html(:rights) %>
10
+ <%= presenter.attribute_to_html(:rights, render_as: :rights) %>
11
11
  </tbody>
12
12
  </table>
@@ -11,7 +11,7 @@
11
11
  <% collection_presenters.each do |collection| %>
12
12
  <ul class="tabular">
13
13
  <li class='attribute title'>
14
- <%= link_to collection.title, main_app.collection_path(collection) %>
14
+ <%= link_to collection.to_s, main_app.collection_path(collection) %>
15
15
  </li>
16
16
  </ul>
17
17
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <div id="descriptions_display" class="tab-pane active">
2
2
  <%= simple_form_for [sufia, @form], html: { multipart: true } do |f| %>
3
3
  <%= hidden_field_tag('redirect_tab', 'descriptions') %>
4
- <h1>Descriptions <span class="pull-right required"><abbr title="required">*</abbr> indicates required fields</span></h1>
4
+ <h1>Description</h1>
5
5
  <% f.object.terms.each do |term| %>
6
6
  <%= render_edit_field_partial(term, f: f) %>
7
7
  <% end %>
@@ -1,19 +1,8 @@
1
- <!DOCTYPE html>
2
- <html lang="<%= t("sufia.document_language") %>">
3
- <head>
4
- <title>Not found</title>
5
- </head>
6
- <body>
7
- <div class="columns two-a">
8
- <div class="column second">
9
- <h1>Not found</h1>
10
- <p>
11
- <%= application_name %> could not locate the requested resource. We
12
- apologize for the inconvenience. You might be interested in using
13
- <a href="/contact/">the contact form</a> to report the
14
- error, or <a href="/help/">the help page</a> for looking up
15
- solutions.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
1
+ <h1>Not found</h1>
2
+ <p>
3
+ <%= application_name %> could not locate the requested resource. We
4
+ apologize for the inconvenience. You might be interested in using
5
+ <a href="/contact/">the contact form</a> to report the
6
+ error, or <a href="/help/">the help page</a> for looking up
7
+ solutions.
8
+ </p>
@@ -10,11 +10,11 @@
10
10
  <!-- application js -->
11
11
  <%= javascript_include_tag 'application' %>
12
12
 
13
- <%= render partial: '/ga', formats: [:html] %>
13
+ <%= render '/ga' %>
14
14
  </head>
15
15
 
16
16
  <body>
17
- <%= render '/masthead', formats: [:html] %>
17
+ <%= render '/masthead' %>
18
18
  <div id="content-wrapper" class="container-fluid">
19
19
  <div class="row">
20
20
  <div class="col-sm-8 col-md-8 col-lg-8">
@@ -22,6 +22,6 @@
22
22
  </div>
23
23
  </div><!-- /.row -->
24
24
  </div><!-- /#content-wrapper -->
25
- <%= render '/footer' %>
25
+ <%= render 'shared/footer' %>
26
26
  </body>
27
27
  </html>
@@ -11,7 +11,7 @@
11
11
  <div id="content-wrapper" class="container-fluid">
12
12
  <%= yield %>
13
13
  </div><!-- /#content-wrapper -->
14
- <%= render partial: '/footer' %>
14
+ <%= render 'shared/footer' %>
15
15
  <%= render 'shared/ajax_modal' %>
16
16
  </body>
17
17
  </html>
@@ -28,7 +28,7 @@
28
28
  </div>
29
29
  </div>
30
30
 
31
- <%= render '/footer' %>
31
+ <%= render 'shared/footer' %>
32
32
  <%= render 'shared/ajax_modal' %>
33
33
  </body>
34
34
  </html>
@@ -26,7 +26,7 @@
26
26
  </div>
27
27
  </div><!-- /.row -->
28
28
  </div><!-- /#content-wrapper -->
29
- <%= render '/footer' %>
29
+ <%= render 'shared/footer' %>
30
30
  <%= render 'shared/ajax_modal' %>
31
31
  </body>
32
32
  </html>
@@ -1,4 +1,4 @@
1
- <footer id="footer" class="navbar navbar-inverse">
1
+ <footer class="navbar navbar-inverse">
2
2
  <div class="container-fluid">
3
3
  <div class="navbar-text text-left">
4
4
  <p>A service of <a href="http://projecthydra.org/" class="navbar-link" target="_blank">Project Hydra</a>.</p>
@@ -1,5 +1,4 @@
1
1
  <!-- Adapted from jquery-flot examples https://github.com/flot/flot/blob/master/examples/visitors/index.html -->
2
- <!--[if lte IE 8]><%= javascript_include_tag 'excanvas' %><![endif]-->
3
2
  <%= javascript_tag do %>
4
3
  var stats = <%= @stats.to_flot.to_json.html_safe %>;
5
4
  <% end %>
@@ -1,6 +1,4 @@
1
1
  <!-- Adapted from jquery-flot examples https://github.com/flot/flot/blob/master/examples/visitors/index.html -->
2
- <!--[if lte IE 8]><%= javascript_include_tag 'excanvas' %><![endif]-->
3
-
4
2
  <%= javascript_tag do %>
5
3
  var stats = <%= @stats.to_flot.to_json.html_safe %>;
6
4
  <% end %>
@@ -103,6 +103,12 @@ module Sufia
103
103
  generate "sufia:proxies"
104
104
  end
105
105
 
106
+ def solr_config
107
+ say_status("info", "GENERATING SUFIA FULL-TEXT", :blue)
108
+ source = File.expand_path("../../../../solr/config/solrconfig.xml", __FILE__)
109
+ copy_file source, 'solr/conf/solrconfig.xml', force: true
110
+ end
111
+
106
112
  # Sets up cached usage stats
107
113
  def cached_stats
108
114
  generate 'sufia:cached_stats'
@@ -5,6 +5,7 @@ module Sufia
5
5
  # These gems must be required outside of an initializer or it doesn't get loaded.
6
6
  require 'breadcrumbs_on_rails'
7
7
  require 'jquery-ui-rails'
8
+ require 'flot-rails'
8
9
  require 'zeroclipboard-rails'
9
10
 
10
11
  config.autoload_paths += %W(