blacklight-spotlight 4.3.0 → 4.3.2
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/spotlight/spotlight.esm.js +1 -1
- data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
- data/app/assets/javascripts/spotlight/spotlight.js +1 -1
- data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
- data/app/components/spotlight/analytics/dashboard_component.html.erb +49 -34
- data/app/components/spotlight/analytics/dashboard_component.rb +71 -3
- data/app/models/concerns/spotlight/exhibit_analytics.rb +2 -6
- data/app/models/spotlight/search.rb +7 -4
- data/app/views/spotlight/sir_trevor/blocks/_embedded_document.html.erb +1 -1
- data/config/locales/spotlight.en.yml +6 -0
- data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +3 -0
- data/lib/spotlight/engine.rb +1 -0
- data/lib/spotlight/version.rb +1 -1
- metadata +3 -3
@@ -1,6 +1,22 @@
|
|
1
|
+
<% if note %>
|
2
|
+
<p><%= note %></p>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= form_with url: helpers.analytics_exhibit_dashboard_path(current_exhibit), class: 'mb-3 d-flex', method: :get do |form| %>
|
6
|
+
<div>
|
7
|
+
<%= form.label :start_date, I18n.t("spotlight.dashboards.analytics.start_date_label") %>
|
8
|
+
<%= form.date_field :start_date, value: dates['start_date'], min: min_date, max: max_date %>
|
9
|
+
<%= form.label :end_date, I18n.t("spotlight.dashboards.analytics.end_date_label"), class: 'ml-2 ms-2' %>
|
10
|
+
<%= form.date_field :end_date, value: dates['end_date'], min: min_date, max: max_date %>
|
11
|
+
</div>
|
12
|
+
<div class="ml-auto ms-auto">
|
13
|
+
<%= form.submit I18n.t("spotlight.dashboards.analytics.submit_date_label"), class: 'btn btn-primary' %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
|
1
17
|
<% if results? %>
|
2
|
-
|
3
|
-
|
18
|
+
<h2><%= heading %></h2>
|
19
|
+
|
4
20
|
<h3 class="h5 mt-4"><%= I18n.t("spotlight.dashboards.analytics.visitor_header") %></h3>
|
5
21
|
<%= render Spotlight::Analytics::AggregationComponent.new(data: page_analytics.totals) %>
|
6
22
|
|
@@ -8,43 +24,42 @@
|
|
8
24
|
<%= render Spotlight::Analytics::AggregationComponent.new(data: search_analytics.totals, exclude_fields: [:eventCount] ) %>
|
9
25
|
|
10
26
|
<% unless page_analytics.rows.empty? %>
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
27
|
+
<h3 class="h5 mt-4"><%= I18n.t("spotlight.dashboards.analytics.pages.header") %></h4>
|
28
|
+
<table class="table table-striped popular-pages">
|
29
|
+
<thead>
|
30
|
+
<tr>
|
31
|
+
<th><%= I18n.t("spotlight.dashboards.analytics.pagetitle") %></th>
|
32
|
+
<th class="text-right text-end"><%= I18n.t("spotlight.dashboards.analytics.pageviews") %></th>
|
33
|
+
</tr>
|
34
|
+
</thead>
|
35
|
+
<% page_analytics.rows.each do |p| %>
|
36
|
+
<tr>
|
37
|
+
<td><%= link_to p.pageTitle, p.pagePath %></td>
|
38
|
+
<td class="text-right text-end"><%= p.screenPageViews %></td>
|
39
|
+
</tr>
|
40
|
+
<% end %>
|
41
|
+
</table>
|
24
42
|
<% end %>
|
25
|
-
</table>
|
26
|
-
<% end %>
|
27
43
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
<tr>
|
33
|
-
<th><%= I18n.t("spotlight.dashboards.analytics.searches.term") %></th>
|
34
|
-
<th class="text-right text-end"><%= I18n.t("spotlight.dashboards.analytics.searches.views") %></th>
|
35
|
-
</tr>
|
36
|
-
</thead>
|
37
|
-
<% search_analytics.rows.each do |p| %>
|
38
|
-
<% if p.searchTerm.present? %>
|
44
|
+
<% unless search_analytics.rows.empty? %>
|
45
|
+
<h3 class="h5 mt-4"><%= I18n.t("spotlight.dashboards.analytics.searches.header") %></h4>
|
46
|
+
<table class="table table-striped popular-pages">
|
47
|
+
<thead>
|
39
48
|
<tr>
|
40
|
-
<
|
41
|
-
<
|
49
|
+
<th><%= I18n.t("spotlight.dashboards.analytics.searches.term") %></th>
|
50
|
+
<th class="text-right text-end"><%= I18n.t("spotlight.dashboards.analytics.searches.views") %></th>
|
42
51
|
</tr>
|
52
|
+
</thead>
|
53
|
+
<% search_analytics.rows.each do |p| %>
|
54
|
+
<% if p.searchTerm.present? %>
|
55
|
+
<tr>
|
56
|
+
<td><%= p.searchTerm %></td>
|
57
|
+
<td class="text-right text-end"><%= p.eventCount %></td>
|
58
|
+
</tr>
|
59
|
+
<% end %>
|
43
60
|
<% end %>
|
44
|
-
|
45
|
-
</table>
|
61
|
+
</table>
|
46
62
|
<% end %>
|
47
|
-
<% end %>
|
48
63
|
<% else %>
|
49
|
-
|
64
|
+
<p><%= I18n.t("spotlight.dashboards.analytics.no_results", pageurl: page_url) %></p>
|
50
65
|
<% end %>
|
@@ -9,7 +9,37 @@ module Spotlight
|
|
9
9
|
def initialize(current_exhibit:)
|
10
10
|
super
|
11
11
|
@current_exhibit = current_exhibit
|
12
|
-
@
|
12
|
+
@default_start_date = [min_date, 1.year.ago].max
|
13
|
+
@default_end_date = [max_date, Time.zone.today].min
|
14
|
+
end
|
15
|
+
|
16
|
+
def before_render
|
17
|
+
flash[:error] = nil
|
18
|
+
@dates = { 'start_date' => @default_start_date.to_date.to_s,
|
19
|
+
'end_date' => @default_end_date.to_date.to_s }
|
20
|
+
|
21
|
+
validate_dates if params[:start_date] || params[:end_date]
|
22
|
+
end
|
23
|
+
|
24
|
+
def min_date
|
25
|
+
Spotlight::Engine.config.ga_date_range['start_date'] || Date.new(2015, 8, 14) # This is the minimum date supported by GA
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_date
|
29
|
+
Spotlight::Engine.config.ga_date_range['end_date'] || Time.zone.today
|
30
|
+
end
|
31
|
+
|
32
|
+
def note
|
33
|
+
I18n.t('spotlight.dashboards.analytics.note', default: nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
def heading
|
37
|
+
if params[:start_date] || params[:end_date]
|
38
|
+
I18n.t('spotlight.dashboards.analytics.reporting_period_heading_dynamic', start_date: formatted_date(dates['start_date']),
|
39
|
+
end_date: formatted_date(dates['end_date']))
|
40
|
+
else
|
41
|
+
I18n.t('spotlight.dashboards.analytics.reporting_period_heading')
|
42
|
+
end
|
13
43
|
end
|
14
44
|
|
15
45
|
def results?
|
@@ -21,11 +51,49 @@ module Spotlight
|
|
21
51
|
end
|
22
52
|
|
23
53
|
def page_analytics
|
24
|
-
|
54
|
+
Rails.cache.fetch([current_exhibit, dates['start_date'], dates['end_date'], 'page_analytics'], expires_in: 1.hour) do
|
55
|
+
current_exhibit.page_analytics(dates, page_url)
|
56
|
+
end
|
25
57
|
end
|
26
58
|
|
27
59
|
def search_analytics
|
28
|
-
|
60
|
+
Rails.cache.fetch([current_exhibit, dates['start_date'], dates['end_date'], 'search_analytics'], expires_in: 1.hour) do
|
61
|
+
current_exhibit.analytics(dates, page_url)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def validate_dates
|
68
|
+
@start_date = parse_date(params[:start_date], min_date)
|
69
|
+
@end_date = parse_date(params[:end_date], max_date)
|
70
|
+
if @start_date > @end_date
|
71
|
+
flash[:error] = I18n.t('spotlight.dashboards.analytics.error_heading', date: "#{@start_date} to #{@end_date}")
|
72
|
+
elsif @start_date < min_date
|
73
|
+
flash[:error] = I18n.t('spotlight.dashboards.analytics.error_heading', date: @start_date)
|
74
|
+
elsif @end_date > max_date
|
75
|
+
flash[:error] = I18n.t('spotlight.dashboards.analytics.error_heading', date: @end_date)
|
76
|
+
else
|
77
|
+
update_dates
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_dates
|
82
|
+
@dates['start_date'] = @start_date.to_date.to_s if parse_date(params[:start_date], nil)
|
83
|
+
@dates['end_date'] = @end_date.to_date.to_s if parse_date(params[:end_date], nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_date(date, backup_date)
|
87
|
+
return backup_date unless date
|
88
|
+
|
89
|
+
Date.parse(date)
|
90
|
+
rescue Date::Error
|
91
|
+
flash[:error] = I18n.t('spotlight.dashboards.analytics.error_heading', date:)
|
92
|
+
backup_date
|
93
|
+
end
|
94
|
+
|
95
|
+
def formatted_date(date_string)
|
96
|
+
Date.parse(date_string).strftime('%m/%d/%Y')
|
29
97
|
end
|
30
98
|
end
|
31
99
|
end
|
@@ -7,17 +7,13 @@ module Spotlight
|
|
7
7
|
def analytics(dates = { start_date: '365daysAgo', end_date: 'today' }, path = nil)
|
8
8
|
return OpenStruct.new unless analytics_provider&.enabled?
|
9
9
|
|
10
|
-
|
11
|
-
start_date = dates['start_date'] || 1.month.ago
|
12
|
-
@analytics[start_date] ||= analytics_provider.exhibit_data(path || self, dates)
|
10
|
+
analytics_provider.exhibit_data(path || self, dates)
|
13
11
|
end
|
14
12
|
|
15
13
|
def page_analytics(dates = { start_date: '365daysAgo', end_date: 'today' }, path = nil)
|
16
14
|
return [] unless analytics_provider&.enabled?
|
17
15
|
|
18
|
-
|
19
|
-
start_date = dates['start_date'] || 1.month.ago
|
20
|
-
@page_analytics[start_date] ||= analytics_provider.page_data(path || self, dates)
|
16
|
+
analytics_provider.page_data(path || self, dates)
|
21
17
|
end
|
22
18
|
|
23
19
|
def analytics_provider
|
@@ -79,13 +79,16 @@ module Spotlight
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def search_params
|
82
|
-
search_service.search_builder.with(
|
82
|
+
search_service.search_builder.with(base_search_state).merge(facet: false)
|
83
83
|
end
|
84
84
|
|
85
85
|
def merge_params_for_search(params, blacklight_config)
|
86
|
-
|
87
|
-
user_query
|
88
|
-
|
86
|
+
user_query = Blacklight::SearchState.new(params, blacklight_config, nil).to_h
|
87
|
+
base_search_state.params_for_search(user_query).merge(user_query.slice(:page))
|
88
|
+
end
|
89
|
+
|
90
|
+
def base_search_state
|
91
|
+
Blacklight::SearchState.new((query_params || {}).with_indifferent_access, blacklight_config, nil)
|
89
92
|
end
|
90
93
|
|
91
94
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="box" data-id="<%= document.id %>">
|
2
2
|
<% view_config = blacklight_config.view_config(:embed) %>
|
3
|
-
<%= render (view_config.document_component || Spotlight::SolrDocumentLegacyEmbedComponent).new((Blacklight.version > '8.0' ? :document : :presenter) => document_presenter(document), counter: nil) do |component| %>
|
3
|
+
<%= render (view_config.document_component || Spotlight::SolrDocumentLegacyEmbedComponent).new((Blacklight.version > '8.0' ? :document : :presenter) => document_presenter(document), counter: nil, block: local_assigns[:block]) do |component| %>
|
4
4
|
<% component.with_partial do %>
|
5
5
|
<%= render_document_partials document, view_config.partials, component: component, document_counter: nil, view_config: view_config, block: local_assigns[:block], **(view_config.locals) %>
|
6
6
|
<% end if view_config&.partials&.any? %>
|
@@ -482,14 +482,18 @@ en:
|
|
482
482
|
dashboards:
|
483
483
|
analytics:
|
484
484
|
activeUsers: unique visits
|
485
|
+
end_date_label: End date
|
485
486
|
engagementRate: engagement rate
|
487
|
+
error_heading: "%{date} does not constitute a valid date range. Please enter a valid date range."
|
486
488
|
header: Analytics
|
487
489
|
no_results: There are no analytics for the path "%{pageurl}"
|
490
|
+
note:
|
488
491
|
pages:
|
489
492
|
header: Most popular pages
|
490
493
|
pagetitle: Page title
|
491
494
|
pageviews: Page views
|
492
495
|
reporting_period_heading: User activity over the past year
|
496
|
+
reporting_period_heading_dynamic: User activity from %{start_date} to %{end_date}
|
493
497
|
screenPageViews: page views
|
494
498
|
screenPageViewsPerSession: pages per session
|
495
499
|
searches:
|
@@ -498,6 +502,8 @@ en:
|
|
498
502
|
views: Searches
|
499
503
|
session_header: Sessions
|
500
504
|
sessions: sessions
|
505
|
+
start_date_label: Start date
|
506
|
+
submit_date_label: Submit
|
501
507
|
totalUsers: visitors
|
502
508
|
users: unique visits
|
503
509
|
visitor_header: Visitors
|
@@ -70,6 +70,8 @@
|
|
70
70
|
# (https://console.cloud.google.com/iam-admin/iam -> Service accounts -> click on service account -> keys)
|
71
71
|
# c) set ga_property_id below to your site's property id (located in admin -> Property -> Property details upper right hand corner)
|
72
72
|
# d) Set the ga_web_property_id. (located in admin -> Data collection and modification -> Web stream details and begins with G-)
|
73
|
+
# e) (optional) set ga_date_range. This allows you throttle the dates the user can filter by.
|
74
|
+
# ga_date_range values should use a Date object i.e. (Date.new(YYYY, MM, DD)).
|
73
75
|
# ga_property_id is used for fetching analytics data from google's api, ga_web_property_id is used for sending events to GA analtyics
|
74
76
|
# ga_web_property_id will probably change in V5 to ga_measurement_id for clarity
|
75
77
|
# Rails.application.config.to_prepare do
|
@@ -77,6 +79,7 @@
|
|
77
79
|
# Spotlight::Engine.config.ga_json_key_path = nil
|
78
80
|
# Spotlight::Engine.config.ga_web_property_id = 'G-XXXXXXXXXX'
|
79
81
|
# Spotlight::Engine.config.ga_property_id = '12345678'
|
82
|
+
# Spotlight::Engine.config.ga_date_range = { 'start_date' => nil, 'end_date' => nil }
|
80
83
|
# Spotlight::Engine.config.ga_analytics_options = {}
|
81
84
|
# Spotlight::Engine.config.ga_page_analytics_options = Spotlight::Engine.config.ga_analytics_options.merge(limit: 5)
|
82
85
|
# Spotlight::Engine.config.ga_search_analytics_options = Spotlight::Engine.config.ga_analytics_options.merge(limit: 11)
|
data/lib/spotlight/engine.rb
CHANGED
@@ -201,6 +201,7 @@ module Spotlight
|
|
201
201
|
config.ga_property_id = nil
|
202
202
|
config.ga_analytics_options = {}
|
203
203
|
config.ga_page_analytics_options = config.ga_analytics_options.merge(limit: 5)
|
204
|
+
config.ga_date_range = { 'start_date' => nil, 'end_date' => nil }
|
204
205
|
config.ga_debug_mode = false
|
205
206
|
|
206
207
|
config.max_pages = 1000
|
data/lib/spotlight/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacklight-spotlight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Beer
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2024-10-
|
14
|
+
date: 2024-10-25 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activejob-status
|
@@ -1586,7 +1586,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1586
1586
|
- !ruby/object:Gem::Version
|
1587
1587
|
version: '0'
|
1588
1588
|
requirements: []
|
1589
|
-
rubygems_version: 3.
|
1589
|
+
rubygems_version: 3.5.9
|
1590
1590
|
signing_key:
|
1591
1591
|
specification_version: 4
|
1592
1592
|
summary: Enable librarians, curators, and others who are responsible for digital collections
|