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.
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(